diff --git a/.htaccess b/.htaccess index addd1a9..5c67abd 100644 --- a/.htaccess +++ b/.htaccess @@ -57,4 +57,8 @@ RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] + # Authorization header + # RewriteCond %{HTTP:Authorization} ^(.*) + # RewriteRule .* - [e=HTTP_AUTHORIZATION:%1] + diff --git a/composer.json b/composer.json index d1c4bc5..98e408d 100644 --- a/composer.json +++ b/composer.json @@ -66,7 +66,10 @@ ] }, "config": { - "preferred-install": "dist" + "preferred-install": "dist", + "allow-plugins": { + "composer/installers": true + } }, "minimum-stability": "dev", "prefer-stable": true diff --git a/config/app.php b/config/app.php index e1ebd3e..3ba7623 100644 --- a/config/app.php +++ b/config/app.php @@ -16,7 +16,7 @@ return [ | */ - 'debug' => true, + 'debug' => env('APP_DEBUG', true), /* |-------------------------------------------------------------------------- @@ -41,7 +41,7 @@ return [ | */ - 'url' => 'http://localhost', + 'url' => env('APP_URL', 'http://localhost'), /* |-------------------------------------------------------------------------- @@ -137,7 +137,7 @@ return [ | */ - 'key' => 'G0tXuSIIGZxHT8GyAhIF38OYxKrdW9CB', + 'key' => env('APP_KEY', ''), 'cipher' => 'AES-256-CBC', diff --git a/config/auth.php b/config/auth.php index 8dc13b6..c95c87b 100644 --- a/config/auth.php +++ b/config/auth.php @@ -1,39 +1,91 @@ [ - /* - |-------------------------------------------------------------------------- - | Enable throttling of Backend authentication attempts - |-------------------------------------------------------------------------- - | - | If set to true, users will be given a limited number of attempts to sign - | in to the Backend before being blocked for a specified number of minutes. - | - */ - 'enabled' => true, - - /* - |-------------------------------------------------------------------------- - | Failed Authentication Attempt Limit - |-------------------------------------------------------------------------- - | - | Number of failed attempts allowed while trying to authenticate a user. - | - */ - 'attemptLimit' => 5, - - /* - |-------------------------------------------------------------------------- - | Suspension Time - |-------------------------------------------------------------------------- - | - | The number of minutes to suspend further attempts on authentication once - | the attempt limit is reached. - | - */ - 'suspensionTime' => 15, + /* + |-------------------------------------------------------------------------- + | Authentication Defaults + |-------------------------------------------------------------------------- + | + | This option controls the default authentication "guard" and password + | reset options for your application. You may change these defaults + | as required, but they're a perfect start for most applications. + | + */ + 'defaults' => [ + 'guard' => env('AUTH_DEFAULT_GUARD', 'web'), + 'passwords' => env('AUTH_DEFAULT_PASSWORDS', 'users'), ], - -]; + /* + |-------------------------------------------------------------------------- + | Authentication Guards + |-------------------------------------------------------------------------- + | + | Next, you may define every authentication guard for your application. + | Of course, a great default configuration has been defined for you + | here which uses session storage and the Eloquent user provider. + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | Supported: "session", "token" + | + */ + 'guards' => [ + 'web' => [ + 'driver' => env('AUTH_GUARDS_WEB_DRIVER', 'session'), + 'provider' => env('AUTH_GUARDS_WEB_PROVIDER', 'users'), + ], + 'api' => [ + 'driver' => env('AUTH_GUARDS_API_DRIVER', 'token'), + 'provider' => env('AUTH_GUARDS_API_PROVIDER', 'users'), + ], + ], + /* + |-------------------------------------------------------------------------- + | User Providers + |-------------------------------------------------------------------------- + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | If you have multiple user tables or models you may configure multiple + | sources which represent each model / table. These sources may then + | be assigned to any extra authentication guards you have defined. + | + | Supported: "database", "eloquent" + | + */ + 'providers' => [ + 'users' => [ + 'driver' => env('AUTH_PROVIDERS_USERS_DRIVER', 'eloquent'), + 'model' => env('AUTH_PROVIDERS_USERS_MODEL', '\RainLab\User\Models\User'), + ], + ], + /* + |-------------------------------------------------------------------------- + | Resetting Passwords + |-------------------------------------------------------------------------- + | + | Here you may set the options for resetting passwords including the view + | that is your password reset e-mail. You may also set the name of the + | table that maintains all of the reset tokens for your application. + | + | You may specify multiple password reset configurations if you have more + | than one user table or model in the application and you want to have + | separate password reset settings based on the specific user types. + | + | The expire time is the number of minutes that the reset token should be + | considered valid. This security feature keeps tokens short-lived so + | they have less time to be guessed. You may change this as needed. + | + */ + 'passwords' => [ + 'users' => [ + 'provider' => env('AUTH_PASSWORDS_USERS_PROVIDER', 'users'), + 'email' => env('AUTH_PASSWORDS_USERS_EMAIL', 'auth.emails.password'), + 'table' => env('AUTH_PASSWORDS_USERS_TABLE', 'password_resets'), + 'expire' => env('AUTH_PASSWORDS_USERS_EXPIRE', 60), + ], + ], +]; \ No newline at end of file diff --git a/config/cache.php b/config/cache.php index c51ef22..93bfc05 100644 --- a/config/cache.php +++ b/config/cache.php @@ -13,7 +13,7 @@ return [ | */ - 'default' => 'file', + 'default' => env('CACHE_DRIVER', 'file'), /* |-------------------------------------------------------------------------- diff --git a/config/cms.php b/config/cms.php index 60ab5e4..02d1f94 100644 --- a/config/cms.php +++ b/config/cms.php @@ -156,7 +156,7 @@ return [ | */ - 'enableRoutesCache' => false, + 'enableRoutesCache' => env('ROUTES_CACHE', false), /* |-------------------------------------------------------------------------- @@ -196,7 +196,7 @@ return [ | */ - 'enableAssetCache' => false, + 'enableAssetCache' => env('ASSET_CACHE', false), /* |-------------------------------------------------------------------------- @@ -250,7 +250,7 @@ return [ | */ - 'databaseTemplates' => false, + 'databaseTemplates' => env('DATABASE_TEMPLATES', false), /* |-------------------------------------------------------------------------- @@ -360,7 +360,7 @@ return [ | */ - 'linkPolicy' => 'detect', + 'linkPolicy' => env('LINK_POLICY', 'detect'), /* |-------------------------------------------------------------------------- @@ -396,7 +396,7 @@ return [ | */ - 'enableCsrfProtection' => true, + 'enableCsrfProtection' => env('ENABLE_CSRF', true), /* |-------------------------------------------------------------------------- diff --git a/config/database.php b/config/database.php index 65a24f8..e2e6a0a 100644 --- a/config/database.php +++ b/config/database.php @@ -26,7 +26,7 @@ return [ | */ - 'default' => 'mysql', + 'default' => env('DB_CONNECTION', 'mysql'), /* |-------------------------------------------------------------------------- @@ -48,18 +48,18 @@ return [ 'sqlite' => [ 'driver' => 'sqlite', - 'database' => 'storage/database.sqlite', + 'database' => env('DB_DATABASE', 'storage/database.sqlite'), 'prefix' => '', ], 'mysql' => [ 'driver' => 'mysql', 'engine' => 'InnoDB', - 'host' => '192.168.1.2', - 'port' => 3306, - 'database' => 'bank_form', - 'username' => 'orient', - 'password' => 'orient', + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', 3306), + 'database' => env('DB_DATABASE', 'halk_bank_form'), + 'username' => env('DB_USERNAME', ''), + 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', @@ -68,11 +68,11 @@ return [ 'pgsql' => [ 'driver' => 'pgsql', - 'host' => 'localhost', - 'port' => 5432, - 'database' => 'database', - 'username' => 'root', - 'password' => '', + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', 5432), + 'database' => env('DB_DATABASE', 'database'), + 'username' => env('DB_USERNAME', ''), + 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'prefix' => '', 'schema' => 'public', @@ -80,11 +80,11 @@ return [ 'sqlsrv' => [ 'driver' => 'sqlsrv', - 'host' => 'localhost', - 'port' => 1433, - 'database' => 'database', - 'username' => 'root', - 'password' => '', + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', 5432), + 'database' => env('DB_DATABASE', 'database'), + 'username' => env('DB_USERNAME', ''), + 'password' => env('DB_PASSWORD', ''), 'prefix' => '', ], @@ -120,9 +120,9 @@ return [ 'cluster' => false, 'default' => [ - 'host' => '127.0.0.1', - 'password' => null, - 'port' => 6379, + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'password' => env('REDIS_PASSWORD', null), + 'port' => env('REDIS_PORT', 6379), 'database' => 0, ], @@ -143,6 +143,6 @@ return [ | */ - 'useConfigForTesting' => false, + 'useConfigForTesting' => env('DB_USE_CONFIG_FOR_TESTING', false), ]; diff --git a/config/mail.php b/config/mail.php index 7773efd..88ca768 100644 --- a/config/mail.php +++ b/config/mail.php @@ -16,7 +16,7 @@ return [ | */ - 'driver' => 'smtp', + 'driver' => env('MAIL_DRIVER', 'smtp'), /* |-------------------------------------------------------------------------- @@ -29,7 +29,7 @@ return [ | */ - 'host' => 'smtp.mailgun.org', + 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), /* |-------------------------------------------------------------------------- @@ -42,7 +42,7 @@ return [ | */ - 'port' => 587, + 'port' => env('MAIL_PORT', 587), /* |-------------------------------------------------------------------------- @@ -71,7 +71,7 @@ return [ | */ - 'encryption' => 'tls', + 'encryption' => env('MAIL_ENCRYPTION', 'tls'), /* |-------------------------------------------------------------------------- @@ -84,7 +84,7 @@ return [ | */ - 'username' => null, + 'username' => env('MAIL_USERNAME', null), /* |-------------------------------------------------------------------------- @@ -97,7 +97,7 @@ return [ | */ - 'password' => null, + 'password' => env('MAIL_PASSWORD', null), /* |-------------------------------------------------------------------------- diff --git a/config/queue.php b/config/queue.php index 660fe0c..cd409c5 100644 --- a/config/queue.php +++ b/config/queue.php @@ -16,7 +16,7 @@ return [ | */ - 'default' => 'sync', + 'default' => env('QUEUE_CONNECTION', 'sync'), /* |-------------------------------------------------------------------------- diff --git a/config/session.php b/config/session.php index 5ad876c..a76b354 100644 --- a/config/session.php +++ b/config/session.php @@ -16,7 +16,7 @@ return [ | */ - 'driver' => 'file', + 'driver' => env('SESSION_DRIVER', 'file'), /* |-------------------------------------------------------------------------- diff --git a/modules/system/reportwidgets/status/partials/_widget.htm b/modules/system/reportwidgets/status/partials/_widget.htm index 855e103..40d7e12 100644 --- a/modules/system/reportwidgets/status/partials/_widget.htm +++ b/modules/system/reportwidgets/status/partials/_widget.htm @@ -4,7 +4,7 @@
+*/ +?> + +makePartial('~/path/to/partial'); + * }); + * + */ + $this->fireViewEvent('rainlab.user.view.extendPreviewToolbar', [ + 'record' => $formModel + ]); +?> diff --git a/plugins/rainlab/user/controllers/users/config_filter.yaml b/plugins/rainlab/user/controllers/users/config_filter.yaml new file mode 100644 index 0000000..797e46f --- /dev/null +++ b/plugins/rainlab/user/controllers/users/config_filter.yaml @@ -0,0 +1,30 @@ +# =================================== +# Filter Scope Definitions +# =================================== + +scopes: + + groups: + # Filter name + label: rainlab.user::lang.group.label + # Model Class name + modelClass: RainLab\User\Models\UserGroup + # Model attribute to display for the name + nameFrom: name + # Filter scope + scope: filterByGroup + + created_date: + label: rainlab.user::lang.user.created_at + type: daterange + conditions: created_at >= ':after' AND created_at <= ':before' + + activated: + # Filter name + label: rainlab.user::lang.user.status_activated + # Filter type + type: switch + # SQL conditions + conditions: + - is_activated = '0' + - is_activated = '1' diff --git a/plugins/rainlab/user/controllers/users/config_form.yaml b/plugins/rainlab/user/controllers/users/config_form.yaml new file mode 100644 index 0000000..7b92abf --- /dev/null +++ b/plugins/rainlab/user/controllers/users/config_form.yaml @@ -0,0 +1,25 @@ +# =================================== +# Form Behavior Config +# =================================== + +# Record name +name: rainlab.user::lang.user.label + +# Model Form Field configuration +form: $/rainlab/user/models/user/fields.yaml + +# Model Class name +modelClass: RainLab\User\Models\User + +# Default redirect location +defaultRedirect: rainlab/user/users + +# Create page +create: + redirect: rainlab/user/users/preview/:id + redirectClose: rainlab/user/users + +# Update page +update: + redirect: rainlab/user/users/update/:id + redirectClose: rainlab/user/users/preview/:id diff --git a/plugins/rainlab/user/controllers/users/config_list.yaml b/plugins/rainlab/user/controllers/users/config_list.yaml new file mode 100644 index 0000000..349ae9e --- /dev/null +++ b/plugins/rainlab/user/controllers/users/config_list.yaml @@ -0,0 +1,40 @@ +# =================================== +# List Behavior Config +# =================================== + +# List Title +title: rainlab.user::lang.users.list_title + +# Model List Column configuration +list: $/rainlab/user/models/user/columns.yaml + +# Model Class name +modelClass: RainLab\User\Models\User + +# Link URL for each record +recordUrl: rainlab/user/users/preview/:id + +# Message to display if the list is empty +noRecordsMessage: backend::lang.list.no_records + +# Records to display per page +recordsPerPage: 20 + +# Display checkboxes next to each record +showCheckboxes: true + +# Displays the list column set up button +showSetup: true + +# Filter widget configuration +filter: config_filter.yaml + +# Toolbar widget configuration +toolbar: + + # Partial for toolbar buttons + buttons: list_toolbar + + # Search widget configuration + search: + prompt: backend::lang.list.search_prompt diff --git a/plugins/rainlab/user/controllers/users/create.htm b/plugins/rainlab/user/controllers/users/create.htm new file mode 100644 index 0000000..f010a3c --- /dev/null +++ b/plugins/rainlab/user/controllers/users/create.htm @@ -0,0 +1,64 @@ + + + + +fatalError): ?> + + + +
+ formRenderOutsideFields() ?> +
+
+ formRenderPrimaryTabs() ?> +
+ +
+
+ + + + + +
+
+ + + + +
formRenderSecondaryTabs() ?>
+ + + + 'layout stretch']) ?> + makeLayout('form-with-sidebar') ?> + + + + +
+ +
+
+

fatalError)) ?>

+

+
+ diff --git a/plugins/rainlab/user/controllers/users/index.htm b/plugins/rainlab/user/controllers/users/index.htm new file mode 100644 index 0000000..766877d --- /dev/null +++ b/plugins/rainlab/user/controllers/users/index.htm @@ -0,0 +1,2 @@ + +listRender() ?> diff --git a/plugins/rainlab/user/controllers/users/preview.htm b/plugins/rainlab/user/controllers/users/preview.htm new file mode 100644 index 0000000..3ff3530 --- /dev/null +++ b/plugins/rainlab/user/controllers/users/preview.htm @@ -0,0 +1,61 @@ + + + + +fatalError): ?> + + + + is_guest): ?> + makePartial('hint_guest') ?> + isBanned()): ?> + makePartial('hint_banned') ?> + trashed()): ?> + makePartial('hint_trashed') ?> + is_activated): ?> + makePartial('hint_activate') ?> + + +
+
+ makePartial('preview_scoreboard') ?> +
+
+ +
+
+ makePartial('preview_toolbar') ?> +
+
+ +
+ formRender(['preview' => true, 'section' => 'outside']) ?> +
+ +
+ formRender(['preview' => true, 'section' => 'primary']) ?> +
+ + + + +
formRender(['preview' => true, 'section' => 'secondary']) ?>
+ + + + 'layout stretch']) ?> + makeLayout('form-with-sidebar') ?> + + + + + +
+

fatalError) ?>

+

+
+ + diff --git a/plugins/rainlab/user/controllers/users/update.htm b/plugins/rainlab/user/controllers/users/update.htm new file mode 100644 index 0000000..6be1c68 --- /dev/null +++ b/plugins/rainlab/user/controllers/users/update.htm @@ -0,0 +1,72 @@ + + + + +fatalError): ?> + + + +
+ formRenderOutsideFields() ?> +
+ +
+ formRenderPrimaryTabs() ?> +
+ +
+
+ + + + + + +
+
+ + + + +
formRenderSecondaryTabs() ?>
+ + + + 'layout stretch']) ?> + makeLayout('form-with-sidebar') ?> + + + + +
+ +
+
+

fatalError)) ?>

+

+
+ diff --git a/plugins/rainlab/user/facades/Auth.php b/plugins/rainlab/user/facades/Auth.php new file mode 100644 index 0000000..5f32208 --- /dev/null +++ b/plugins/rainlab/user/facades/Auth.php @@ -0,0 +1,15 @@ + [ + 'name' => 'Uživatelé', + 'description' => 'Správa front-end uživatelů.', + 'tab' => 'Uživatelé', + 'access_users' => 'Správa uživatelů', + 'access_groups' => 'Správa uživatelských skupin', + 'access_settings' => 'Správa nastavení uživatelů', + ], + 'users' => [ + 'menu_label' => 'Uživatelé', + 'all_users' => 'Seznam uživatelů', + 'new_user' => 'VytvoÅ™it uživatele', + 'list_title' => 'Správa uživatelů', + 'activating' => 'Povoluji...', + 'trashed_hint_title' => 'Uživatel deaktivoval svůj úÄet', + 'trashed_hint_desc' => 'Uživatel zablokoval svůj úÄet a nechce se dále objevovat na stránkách. Může vÅ¡ak svůj úÄet kdykoli obnovit pÅ™ihlášením se zpÄ›t.', + 'banned_hint_title' => 'Uživatel byl zabanován', + 'banned_hint_desc' => 'Tento uživatel byl zablokován administrátorem a nebude moct se pÅ™ihlásit.', + 'guest_hint_title' => 'Tento uživatel je host', + 'guest_hint_desc' => 'Tento uživatel je uložen pouze jako reference a musí se zaregistrovat pÅ™ed pÅ™ihlášením.', + 'activate_warning_title' => 'Uživatel není aktivní!', + 'activate_warning_desc' => 'Tento uživatel nemohl být aktivován a nebude mít možnost se pÅ™ihlásit.', + 'activate_confirm' => 'Opravdu chcete aktivovat tohoto uživatele?', + 'activated_success' => 'Uživatel byl úspěšnÄ› aktivován!', + 'activate_manually' => 'Aktivovat uživatele manuálnÄ›', + 'convert_guest_confirm' => 'Chcete pÅ™evést hosta na uživatele?', + 'convert_guest_manually' => 'PÅ™evést na zaregistrovaného uživatele', + 'convert_guest_success' => 'Uživatel byl pÅ™eveden na registrovaného uživatele', + 'delete_confirm' => 'Opravdu chcete smazat tohoto uživatele?', + 'unban_user' => 'ZruÅ¡it ban tohoto uživatele', + 'unban_confirm' => 'Opravdu chcete zruÅ¡it ban tohoto uživatele?', + 'unbanned_success' => 'Uživateli byl zruÅ¡en ban', + 'return_to_list' => 'ZpÄ›t na seznam uživatelů', + 'update_details' => 'Upravit detaily', + 'bulk_actions' => 'Hromadné akce', + 'delete_selected' => 'Odstranit vybrané', + 'delete_selected_confirm' => 'Chcete smazat vybrané uživatele?', + 'delete_selected_empty' => 'Nejdříve vyberte uživatele, které chcete smazat.', + 'delete_selected_success' => 'Vybraní uživatelé úspěšnÄ› odstranÄ›ni.', + 'deactivate_selected' => 'Deaktivovat vybrané', + 'deactivate_selected_confirm' => 'Deaktivovat vybrané uživatele?', + 'deactivate_selected_empty' => 'Musíte vybrat uživatele, které chcete deaktivovat.', + 'deactivate_selected_success' => 'Vybraní uživatelé byli úspěšnÄ› deaktivování.', + 'restore_selected' => 'Obnovit vybrané', + 'restore_selected_confirm' => 'Opravdu chcete obnovit vybrané uživatele?', + 'restore_selected_empty' => 'Musíte vybrat uživatele, které chcete obnovit.', + 'restore_selected_success' => 'Vybraní uživatele byli úspěšnÄ› obnoveni.', + 'ban_selected' => 'Zabanovat vybrané', + 'ban_selected_confirm' => 'Opravdu chcete zabanovat vybrané uživatele?', + 'ban_selected_empty' => 'Musíte vybrat uživatele, které chcete zabanovat.', + 'ban_selected_success' => 'Vybraní uživatelé byli úspěšnÄ› zabanováni.', + 'unban_selected' => 'Odbanovat vybrané', + 'unban_selected_confirm' => 'Opravdu chcete odbanovat vybrané uživatele?', + 'unban_selected_empty' => 'Musíte vybrat uživatele, které chcete odbanovat.', + 'unban_selected_success' => 'Vybraní uživatelé byli úspěšnÄ› odbanováni.', + ], + 'settings' => [ + 'users' => 'Uživatelé', + 'menu_label' => 'Správa uživatelů', + 'menu_description' => 'Správa nastavení uživatelů', + 'activation_tab' => 'Aktivace', + 'signin_tab' => 'PÅ™ihlášení', + 'registration_tab' => 'Registrace', + 'notifications_tab' => 'Notifikace', + 'allow_registration' => 'Povolit registraci uživatelů', + 'allow_registration_comment' => 'Pokud je registrace zakázaná, uživatelé lze vytvářet pouze v administraci.', + 'activate_mode' => 'Režim aktivace', + 'activate_mode_comment' => 'Vyberte jak má být uživatel aktivován.', + 'activate_mode_auto' => 'Automaticky', + 'activate_mode_auto_comment' => 'Aktivován automaticky ihned po registraci.', + 'activate_mode_user' => 'AktivaÄní e-mail', + 'activate_mode_user_comment' => 'Uživatel si aktivuje úÄet pomocí aktivaÄního e-mailu.', + 'activate_mode_admin' => 'Administrátorem', + 'activate_mode_admin_comment' => 'Pouze administrátor může aktivovat uživatele.', + 'require_activation' => 'PÅ™ihlášení vyžaduje aktivaci uživatele', + 'require_activation_comment' => 'Uživatelé musí mít aktivovaný úÄet, aby se mohl pÅ™ihlásit.', + 'use_throttle' => 'Omezit opakované pokusy o pÅ™ihlášení', + 'use_throttle_comment' => 'PÅ™i opakovaném pokusu o pÅ™ihlášení dojde k suspendování uživatele.', + 'login_attribute' => 'PÅ™ihlaÅ¡ovací atribut', + 'login_attribute_comment' => 'Zvolte, jaký atribut bude použitý k pÅ™ihlášení uživatele.', + ], + 'user' => [ + 'label' => 'Uživatel', + 'id' => 'ID', + 'username' => 'Uživatelské jméno', + 'name' => 'Jméno', + 'name_empty' => 'Anonym', + 'surname' => 'Příjmení', + 'email' => 'E-mail', + 'created_at' => 'Datum registrace', + 'last_seen' => 'Poslední pÅ™ihlášení', + 'is_guest' => 'Host', + 'joined' => 'Registrován', + 'is_online' => 'Nyní on-line', + 'is_offline' => 'Nyní offline', + 'send_invite' => 'Poslat pozvánku e-mailem', + 'send_invite_comment' => 'Poslat uvítací e-mail obsahující pÅ™ihlaÅ¡ovací jméno a heslo.', + 'create_password' => 'VytvoÅ™it heslo', + 'create_password_comment' => 'Zadejte heslo které se bude používat k pÅ™ihlaÅ¡ování.', + 'reset_password' => 'Nové heslo', + 'reset_password_comment' => 'Pro zmÄ›nu hesla, zadejte nové heslo.', + 'confirm_password' => 'Nové heslo znovu pro kontrolu', + 'confirm_password_comment' => 'Zadejte heslo znovu pro kontrolu správnosti.', + 'groups' => 'Skupiny', + 'empty_groups' => 'V této skupinÄ› nejsou žádní uživatelé.', + 'avatar' => 'Obrázek', + 'details' => 'Detaily', + 'account' => 'ÚÄet', + 'block_mail' => 'Zablokovat vÅ¡echny odchozí e-maily pro tohoto uživatele.', + 'status_guest' => 'Host', + 'status_activated' => 'Aktivován', + 'status_registered' => 'Registrován', + ], + 'group' => [ + 'label' => 'Skupina', + 'id' => 'ID', + 'name' => 'Název', + 'description_field' => 'Popis skupiny', + 'code' => 'Kód', + 'code_comment' => 'Zadejte unikátní kód pro jednoznaÄnou identifikaci této skupiny.', + 'created_at' => 'VytvoÅ™eno', + 'users_count' => 'PoÄet uživatelů', + ], + 'groups' => [ + 'menu_label' => 'Skupiny', + 'all_groups' => 'Uživatelské skupiny', + 'new_group' => 'Nová skupina', + 'delete_selected_confirm' => 'Opravdu chcete smazat vybrané skupiny?', + 'list_title' => 'Správa skupin', + 'delete_confirm' => 'Opravdu chcete odstranit tuto skupinu?', + 'delete_selected_success' => 'Vybrané skupiny byly úspěšnÄ› odstranÄ›ny.', + 'delete_selected_empty' => 'Musíte nejdřív vybrat skupiny které chcete smazat.', + 'return_to_list' => 'ZpÄ›t na seznam skupin', + 'return_to_users' => 'ZpÄ›t na seznam uživatelů', + 'create_title' => 'VytvoÅ™it skupinu', + 'update_title' => 'Upravit skupinu', + 'preview_title' => 'Náhled skupiny', + ], + 'login' => [ + 'attribute_email' => 'E-mail', + 'attribute_username' => 'Uživatelské jméno', + ], + 'account' => [ + 'account' => 'Správa úÄtu', + 'account_desc' => 'Formuláře správy úÄtu a pÅ™ihlášení', + 'redirect_to' => 'PÅ™esmÄ›rovat na', + 'redirect_to_desc' => 'Název stránky pro pÅ™esmÄ›rování po úpravÄ› údajů, pÅ™ihlášení nebo registraci.', + 'code_param' => 'Parametr aktivaÄního kódu', + 'code_param_desc' => 'Parametr z URL stránky, který se použije pro aktivaÄní kód', + 'invalid_user' => 'Uživatel s tÄ›mito údaji nebyl nalezen.', + 'invalid_activation_code' => 'Zadán nesprávný parametr pro aktivaÄní kód', + 'invalid_deactivation_pass' => 'Zadané heslo není správné.', + 'success_activation' => 'Váš úÄet byl úspěšnÄ› aktivován.', + 'success_deactivation' => 'Váš úÄet byl úspěšnÄ› deaktivován. Mrzí nás, že odcházíte!', + 'success_saved' => 'Nastavení bylo úspěšnÄ› uloženo!', + 'login_first' => 'Nejdříve musíte být pÅ™ihlášeni!', + 'already_active' => 'Váš úÄet je již aktivován!', + 'activation_email_sent' => 'AktivaÄní e-mail byl zaslán na e-mail, který byl zadán pÅ™i registraci.', + 'registration_disabled' => 'Registrace jsou doÄasnÄ› pozastaveny.', + 'sign_in' => 'PÅ™ihlášení', + 'register' => 'Registrace', + 'full_name' => 'Celé jméno', + 'email' => 'E-mail', + 'password' => 'Heslo', + 'login' => 'PÅ™ihlášení', + 'new_password' => 'Nové heslo', + 'new_password_confirm' => 'Potvrzení nového hesla' + ], + 'reset_password' => [ + 'reset_password' => 'Obnova hesla', + 'reset_password_desc' => 'Formulář obnovy hesla', + 'code_param' => 'Parametr kódu pro obnovu hesla', + 'code_param_desc' => 'Parametr URL použitý pro obnovu hesla' + ], + 'session' => [ + 'session' => 'Session', + 'session_desc' => 'Vloží do stránky informace o pÅ™ihlášení s možností omezení přístupových práv.', + 'security_title' => 'Povolit pouze', + 'security_desc' => 'Kdo má přístup k této stránce.', + 'all' => 'VÅ¡ichni', + 'users' => 'Uživatelé', + 'guests' => 'Hosti', + 'redirect_title' => 'PÅ™esmÄ›rovat na', + 'redirect_desc' => 'Stránka pro pÅ™esmÄ›rování, pokud je přístup zamítnut.', + 'logout' => 'Byli jste úspěšnÄ› odhlášeni!' + ] +]; diff --git a/plugins/rainlab/user/lang/de/lang.php b/plugins/rainlab/user/lang/de/lang.php new file mode 100644 index 0000000..a87f58b --- /dev/null +++ b/plugins/rainlab/user/lang/de/lang.php @@ -0,0 +1,248 @@ + [ + 'name' => 'Benutzer', + 'description' => 'Frontend-Benutzer-Verwaltung.', + 'tab' => 'Benutzer', + 'access_users' => 'Benutzer verwalten', + 'access_groups' => 'Benutzergruppen verwalten', + 'access_settings' => 'Benutzereinstellungen verwalten', + 'impersonate_user' => 'Als Benutzer einloggen', + ], + 'location' => [ + 'label' => 'Standort', + 'new' => 'Neuer Standort', + 'create_title' => 'Standort anlegen', + 'update_title' => 'Standort bearbeiten', + 'preview_title' => 'Standort ansehen', + ], + 'locations' => [ + 'menu_label' => 'Standorte', + 'menu_description' => 'Verfügbare Benutzer-Standorte und Provinzen verwalten.', + 'hide_disabled' => 'Deaktivierte verbergen', + 'enabled_label' => 'Aktiviert', + 'enabled_help' => 'Deaktivierte Standorte sind im Frontend nicht sichtbar.', + 'enable_or_disable_title' => 'Standorte aktivieren oder deaktivieren', + 'enable_or_disable' => 'Aktivieren oder deaktivieren', + 'selected_amount' => 'Standorte ausgewählt: :amount', + 'enable_success' => 'Standorte erfolgreich aktiviert.', + 'disable_success' => 'Standorte erfolgreich deaktiviert.', + 'disable_confirm' => 'Sind Sie sicher?', + 'list_title' => 'Standorte verwalten', + 'delete_confirm' => 'Möchten Sie diesen Standort wirklich löschen?', + 'return_to_list' => 'Zurück zur Standortliste', + ], + 'users' => [ + 'menu_label' => 'Benutzer', + 'all_users' => 'Alle Benutzer', + 'new_user' => 'Neuer Benutzer', + 'list_title' => 'Benutzer verwalten', + 'trashed_hint_title' => 'Benutzer hat sein Konto deaktiviert.', + 'trashed_hint_desc' => 'Dieser Benutzer hat sein Konto deaktiviert und möchte nicht mehr auf der Seite erscheinen. Er kann sein Konto jederzeit durch eine Anmeldung reaktivieren.', + 'banned_hint_title' => 'Benutzer wurde gesperrt.', + 'banned_hint_desc' => 'Dieser Benutzer wurde von einem Adminstrator gesperrt und kann sich somit nicht mehr anmelden.', + 'guest_hint_title' => 'Dieser Benutzer ist ein Gast', + 'guest_hint_desc' => 'Dieser Benutzer ist nur zu Referenzzwecken gespeichert und muss sich vor dem nächsten Login nochmals registrieren.', + 'activate_warning_title' => 'Benutzer nicht aktiviert!', + 'activate_warning_desc' => 'Dieser Benutzer wurde noch nicht aktiviert und kann sich nicht einloggen.', + 'activate_confirm' => 'Möchten Sie diesen Benutzer wirklich aktivieren?', + 'activated_success' => 'Benutzer erfolgreich aktiviert!', + 'activate_manually' => 'Benutzer manuell aktivieren', + 'convert_guest_confirm' => 'Soll dieser Benutzer zu einem Gast umgewandelt werden?', + 'convert_guest_manually' => 'Benutzer zu einem Gast umwandeln', + 'convert_guest_success' => 'Der Benutzer wurde zu einem Gast umgewandelt', + 'impersonate_user' => 'Als Benutzer einloggen', + 'impersonate_confirm' => 'Soll die Anmeldung mit diesem Benutzerkonto erfolgen? Nach der Abmeldung wird die bestehende Sitzung wiederhergestellt.', + 'impersonate_success' => 'Sie sind nun als diesen Benutzer angemeldet', + 'delete_confirm' => 'Möchten Sie diesen Benutzer wirklich löschen?', + 'unban_user' => 'Diesen Benutzer entsperren', + 'unban_confirm' => 'Möchten Sie diesen Benutzer wirklich entsperren?', + 'unbanned_success' => 'Der Benutzer wurde entsperrt', + 'return_to_list' => 'Zurück zur Benutzerliste', + 'update_details' => 'Update details', + 'bulk_actions' => 'Stapelbearbeitung', + 'delete_selected' => 'Ausgewählte löschen', + 'delete_selected_confirm' => 'Ausgewählte Benutzer löschen?', + 'delete_selected_empty' => 'Keine Benutzer zum Löschen ausgewählt.', + 'delete_selected_success' => 'Ausgewählte Benutzer erfolgreich gelöscht.', + 'activate_selected' => 'Ausgewählte aktivieren', + 'activate_selected_confirm' => 'Sollten die ausgewählten Benutzer aktiviert werden?', + 'activate_selected_empty' => 'Es sind keine Benutzer zur Aktivierung ausgewählt.', + 'activate_selected_success' => 'Die ausgewählten Benutzer wurden erfolgreich aktiviert.', + 'deactivate_selected' => 'Ausgewählte deaktivieren', + 'deactivate_selected_confirm' => 'Ausgewählte Benutzer deaktivieren?', + 'deactivate_selected_empty' => 'Es wurden keine Benutzer zum Deaktivieren ausgewählt.', + 'deactivate_selected_success' => 'Ausgewählte Benutzer erfolgreich deaktiviert.', + 'restore_selected' => 'Ausgewählte wiederherstellen', + 'restore_selected_confirm' => 'Ausgewählte Benutzer wiederherstellen?', + 'restore_selected_empty' => 'Es wurden keine Benutzer zum Wiederherstellen ausgewählt.', + 'restore_selected_success' => 'Ausgewählte Benutzer erfolgreich wiederhergestellt.', + 'ban_selected' => 'Ausgewählte sperren', + 'ban_selected_confirm' => 'Ausgewählte Benutzer sperren?', + 'ban_selected_empty' => 'Es wurden keine Benutzer zum Sperren ausgewählt.', + 'ban_selected_success' => 'Ausgewählte Benutzer erfolgreich gesperrt.', + 'unban_selected' => 'Ausgewählte entsperren', + 'unban_selected_confirm' => 'Ausgewählte Benutzer entsperren?', + 'unban_selected_empty' => 'Es wurden keine Benutzer zum Entsperren ausgewählt.', + 'unban_selected_success' => 'Ausgewählte Benutzer erfolgreich entsperrt.', + 'activating' => 'Aktiviere...', + ], + 'settings' => [ + 'users' => 'Benutzer', + 'menu_label' => 'Benutzer-Einstellungen', + 'menu_description' => 'Benutzer-Einstellungen verwalten.', + 'activation_tab' => 'Aktivierung', + 'signin_tab' => 'Einloggen', + 'registration_tab' => 'Registrierungen', + 'notifications_tab' => 'Benachrichtigungen', + 'allow_registration' => 'Benutzerregistrierung erlauben', + 'allow_registration_comment' => 'Falls dies deaktivert ist, können Benutzer nur von Administratoren erstellt werden.', + 'activate_mode' => 'Aktivierungsmodus', + 'activate_mode_comment' => 'Wählen Sie aus, wie ein Benutzer aktiviert werden soll.', + 'activate_mode_auto' => 'Automatisch', + 'activate_mode_auto_comment' => 'Automatische Aktivierung bei Registrierung.', + 'activate_mode_user' => 'Benutzer', + 'activate_mode_user_comment' => 'Der Benutzer aktiviert seinen eigenes Konto per E-Mail.', + 'activate_mode_admin' => 'Administrator', + 'activate_mode_admin_comment' => 'Nur ein Administrator kann einen Benutzer aktivieren.', + 'require_activation' => 'Anmeldung benötigt Aktivierung', + 'require_activation_comment' => 'Benutzer müssen zum Einloggen ein aktiviertes Konto besitzen.', + 'use_throttle' => 'Anmeldeversuche begrenzen', + 'use_throttle_comment' => 'Bei wiederholten Anmelde-Fehlversuchen wird der Benutzer temporär gesperrt.', + 'block_persistence' => 'Gleichzeitige Anmeldung unterbinden', + 'block_persistence_comment' => 'Wird diese Option aktiviert kann sich ein Benutzer nicht an mehreren Geräten gleichzeitig anmelden.', + 'login_attribute' => 'Anmelde-Attribut-Zuordnung', + 'login_attribute_comment' => 'Wählen Sie, welches Benutzerattribut zum Anmelden verwendet werden soll.', + 'location_tab' => 'Standort', + 'default_country' => 'Standort-Voreinstellung', + 'default_country_comment' => 'Wenn ein Benutzer keinen Standort angibt, wird dieser Standort als Standard gewählt.', + 'default_state' => 'Provinz-Voreinstellung', + 'default_state_comment' => 'Wenn ein Benutzer keinen Standort angibt, wird diese Provinz als Standard gewählt.', + ], + 'state' => [ + 'label' => 'Provinz', + 'name' => 'Name', + 'name_comment' => 'Anzeigenamen für diese Provinz eingeben.', + 'code' => 'Code', + 'code_comment' => 'Eindeutigen Code für diese Provinz eingeben.', + ], + 'country' => [ + 'label' => 'Land', + 'name' => 'Name', + 'code' => 'Code', + 'code_comment' => 'Eindeutigen Code für dieses Land eingeben.', + 'enabled' => 'Aktiv', + ], + 'user' => [ + 'label' => 'Benutzer', + 'id' => 'ID', + 'username' => 'Benutzername', + 'name' => 'Name', + 'name_empty' => 'Anonym', + 'surname' => 'Nachname', + 'email' => 'E-Mail', + 'created_at' => 'Registriert am', + 'last_seen' => 'Zuletzt gesehen', + 'is_guest' => 'Gast', + 'joined' => 'Registriert', + 'is_online' => 'Jetzt online', + 'is_offline' => 'Momentan offline', + 'send_invite' => 'Einladung per E-Mail versenden', + 'send_invite_comment' => 'Sendet eine E-Mail mit Benutzername und Passwort and den Benutzer', + 'create_password' => 'Passwort erstellen', + 'create_password_comment' => 'Gib ein neues Passwort ein, das zum Anmelden verwendet wird.', + 'reset_password' => 'Passwort setzen', + 'reset_password_comment' => 'Geben Sie hier ein Passwort ein, um das aktuelle Benutzerpasswort zu überschreiben.', + 'confirm_password' => 'Passwort bestätigen', + 'confirm_password_comment' => 'Passwort zur Bestätigung erneut eingeben.', + 'groups' => 'Gruppen', + 'empty_groups' => 'Es gibt keine Benutzer-Gruppen.', + 'avatar' => 'Avatar', + 'details' => 'Details', + 'account' => 'Benutzerkonto', + 'block_mail' => 'Blockiere alle ausgehenden E-Mails an diesen Benutzer.', + 'status_guest' => 'Gast', + 'status_activated' => 'Aktiviert', + 'status_registered' => 'Registriert', + ], + 'login' => [ + 'attribute_email' => 'E-Mail', + 'attribute_username' => 'Benutzername', + ], + 'account' => [ + 'account' => 'Benutzerkonto', + 'account_desc' => 'Benutzerkontoverwaltung.', + 'banned' => 'Sorry, dieser Benutzer ist momentan nicht aktiviert. Kontaktieren Sie uns für weitere Unterstützung.', + 'redirect_to' => 'Weiterleiten nach', + 'redirect_to_desc' => 'Seitenname zum Weiterleiten nach Update, Anmeldung oder Registrierung.', + 'code_param' => 'Aktivierungscode Parameter', + 'code_param_desc' => 'Dieser URL-Parameter wird als Registrierungs-Aktivierungscode verwendet', + 'force_secure' => 'Forciere sichere URLs', + 'force_secure_desc' => 'Verwende für Weiterleitungen immer das HTTPS-Protokoll.', + 'invalid_user' => 'Es wurde kein Benutzer mit diesen Zugangsdaten gefunden.', + 'invalid_activation_code' => 'Ungültiger Aktivierungscode übermittelt', + 'invalid_deactivation_pass' => 'Das eingegebene Passwort war ungültig.', + 'success_activation' => 'Benutzerkonto erfolgreich aktiviert.', + 'success_deactivation' => 'Konto erfolgreich deaktiviert. Schade, dass du gehst!', + 'success_saved' => 'Einstellungen erfolgreich gespeichert!', + 'login_first' => 'Sie müssen sich erst einloggen!', + 'already_active' => 'Ihr Benutzerkonto ist bereits aktiviert!', + 'activation_email_sent' => 'Eine Aktivierungs-E-Mail wurde an Ihre E-Mail-Adresse versendet.', + 'registration_disabled' => 'Registrierungen sind momentan deaktiviert.', + 'sign_in' => 'Anmelden', + 'register' => 'Registrieren', + 'full_name' => 'Name', + 'email' => 'E-Mail', + 'password' => 'Passwort', + 'login' => 'Anmelden', + 'new_password' => 'Neues Passwort', + 'new_password_confirm' => 'Neues Passwort bestätigen', + ], + 'reset_password' => [ + 'reset_password' => 'Passwort zurücksetzen', + 'reset_password_desc' => 'Formular zum Zurücksetzen des Passworts.', + 'code_param' => 'Reset-Code-Parameter', + 'code_param_desc' => 'URL-Parameter, der für den Reset-Code verwendet wird', + ], + 'session' => [ + 'session' => 'Session', + 'session_desc' => 'Fügt Benutzer-Session zu Seite hinzu und kann Zugriff einschränken.', + 'security_title' => 'Erlauben', + 'security_desc' => 'Wer hat Zugriff auf die Seite?', + 'all' => 'Jeder', + 'users' => 'Benutzer', + 'guests' => 'Gäste', + 'allowed_groups_title' => 'Gruppen zulassen', + 'allowed_groups_description' => 'Wählen Sie zugelassene Gruppen aus. Wird keine Gruppe ausgewhält sind alle zugelassen.', + 'redirect_title' => 'Weiterleiten nach', + 'redirect_desc' => 'Seitenname zum Weiterleiten bei verweigertem Zugriff.', + 'logout' => 'Sie haben sich erfolgreich ausgeloggt!', + 'stop_impersonate_success' => 'Sie sind nicht mehr als diesen Benutzer angemeldet.', + ], + 'group' => [ + 'label' => 'Gruppe', + 'id' => 'ID', + 'name' => 'Name', + 'description_field' => 'Beschreibung', + 'code' => 'Code', + 'code_comment' => 'Gebe einen eindeutigen Code ein, der die Gruppe identifiziert.', + 'created_at' => 'Erstellt am', + 'users_count' => 'Benutzer', + ], + 'groups' => [ + 'menu_label' => 'Gruppen', + 'all_groups' => 'Benutzergruppen', + 'new_group' => 'Neue Gruppe', + 'delete_selected_confirm' => 'Willst du die ausgewählten Gruppen wirklich löschen?', + 'list_title' => 'Gruppen verwalten', + 'delete_confirm' => 'Willst du diese Gruppe wirklich löschen?', + 'delete_selected_success' => 'Ausgewählte Gruppen erfolgreich gelöscht.', + 'delete_selected_empty' => 'Es wurden keine Gruppen zum Löschen ausgewählt.', + 'return_to_list' => 'Zurück zur Gruppenliste', + 'return_to_users' => 'Zurück zur Benutzerliste', + 'create_title' => 'Benutzergruppe erstellen', + 'update_title' => 'Benutzergruppe bearbeiten', + 'preview_title' => 'Vorschau der Benutzergruppe', + ], +]; diff --git a/plugins/rainlab/user/lang/en/lang.php b/plugins/rainlab/user/lang/en/lang.php new file mode 100644 index 0000000..6044b42 --- /dev/null +++ b/plugins/rainlab/user/lang/en/lang.php @@ -0,0 +1,228 @@ + [ + 'name' => 'User', + 'description' => 'Front-end user management.', + 'tab' => 'Users', + 'access_users' => 'Manage Users', + 'access_groups' => 'Manage User Groups', + 'access_settings' => 'Manage User Settings', + 'impersonate_user' => 'Impersonate Users' + ], + 'users' => [ + 'menu_label' => 'Users', + 'all_users' => 'All Users', + 'new_user' => 'New User', + 'list_title' => 'Manage Users', + 'trashed_hint_title' => 'User has deactivated their account', + 'trashed_hint_desc' => 'This user has deactivated their account and no longer wants to appear on the site. They can restore their account at any time by signing back in.', + 'banned_hint_title' => 'User has been banned', + 'banned_hint_desc' => 'This user has been banned by an administrator and will be unable to sign in.', + 'guest_hint_title' => 'This is a guest user', + 'guest_hint_desc' => 'This user is stored for reference purposes only and needs to register before signing in.', + 'activate_warning_title' => 'User not activated!', + 'activate_warning_desc' => 'This user has not been activated and may be unable to sign in.', + 'activate_confirm' => 'Do you really want to activate this user?', + 'activated_success' => 'User has been activated', + 'activate_manually' => 'Activate this user manually', + 'convert_guest_confirm' => 'Convert this guest to a user?', + 'convert_guest_manually' => 'Convert to registered user', + 'convert_guest_success' => 'User has been converted to a registered account', + 'impersonate_user' => 'Impersonate user', + 'impersonate_confirm' => 'Impersonate this user? You can revert to your original state by logging out.', + 'impersonate_success' => 'You are now impersonating this user', + 'delete_confirm' => 'Do you really want to delete this user?', + 'unban_user' => 'Unban this user', + 'unban_confirm' => 'Do you really want to unban this user?', + 'unbanned_success' => 'User has been unbanned', + 'return_to_list' => 'Return to users list', + 'update_details' => 'Update details', + 'bulk_actions' => 'Bulk actions', + 'delete_selected' => 'Delete selected', + 'delete_selected_confirm' => 'Delete the selected users?', + 'delete_selected_empty' => 'There are no selected users to delete.', + 'delete_selected_success' => 'Successfully deleted the selected users.', + 'activate_selected' => 'Activate selected', + 'activate_selected_confirm' => 'Activate the selected users?', + 'activate_selected_empty' => 'There are no selected users to activate.', + 'activate_selected_success' => 'Successfully activated the selected users.', + 'deactivate_selected' => 'Deactivate selected', + 'deactivate_selected_confirm' => 'Deactivate the selected users?', + 'deactivate_selected_empty' => 'There are no selected users to deactivate.', + 'deactivate_selected_success' => 'Successfully deactivated the selected users.', + 'restore_selected' => 'Restore selected', + 'restore_selected_confirm' => 'Restore the selected users?', + 'restore_selected_empty' => 'There are no selected users to restore.', + 'restore_selected_success' => 'Successfully restored the selected users.', + 'ban_selected' => 'Ban selected', + 'ban_selected_confirm' => 'Ban the selected users?', + 'ban_selected_empty' => 'There are no selected users to ban.', + 'ban_selected_success' => 'Successfully banned the selected users.', + 'unban_selected' => 'Unban selected', + 'unban_selected_confirm' => 'Unban the selected users?', + 'unban_selected_empty' => 'There are no selected users to unban.', + 'unban_selected_success' => 'Successfully unbanned the selected users.', + 'unsuspend' => 'Unsuspend', + 'unsuspend_success' => 'User has been unsuspended.', + 'unsuspend_confirm' => 'Unsuspend this user?' + ], + 'settings' => [ + 'users' => 'Users', + 'menu_label' => 'User settings', + 'menu_description' => 'Manage user authentication, registration and activation settings.', + 'activation_tab' => 'Activation', + 'signin_tab' => 'Sign in', + 'registration_tab' => 'Registration', + 'profile_tab' => 'Profile', + 'notifications_tab' => 'Notifications', + 'allow_registration' => 'Allow user registration', + 'allow_registration_comment' => 'If this is disabled users can only be created by administrators.', + 'activate_mode' => 'Activation mode', + 'activate_mode_comment' => 'Select how a user account should be activated.', + 'activate_mode_auto' => 'Automatic', + 'activate_mode_auto_comment' => 'Activated automatically upon registration.', + 'activate_mode_user' => 'User', + 'activate_mode_user_comment' => 'The user activates their own account using mail.', + 'activate_mode_admin' => 'Administrator', + 'activate_mode_admin_comment' => 'Only an Administrator can activate a user.', + 'require_activation' => 'Sign in requires activation', + 'require_activation_comment' => 'Users must have an activated account to sign in.', + 'use_throttle' => 'Throttle attempts', + 'use_throttle_comment' => 'Repeat failed sign in attempts will temporarily suspend the user.', + 'use_register_throttle' => 'Throttle registration', + 'use_register_throttle_comment' => 'Prevent multiple registrations from the same IP in short succession.', + 'block_persistence' => 'Prevent concurrent sessions', + 'block_persistence_comment' => 'When enabled users cannot sign in to multiple devices at the same time.', + 'login_attribute' => 'Login attribute', + 'login_attribute_comment' => 'Select what primary user detail should be used for signing in.', + 'remember_login' => 'Remember login mode', + 'remember_login_comment' => 'Select if the user session should be persistent.', + 'remember_always' => 'Always', + 'remember_never' => 'Never', + 'remember_ask' => 'Ask the user on login', + ], + 'user' => [ + 'label' => 'User', + 'id' => 'ID', + 'username' => 'Username', + 'name' => 'Name', + 'name_empty' => 'Anonymous', + 'surname' => 'Surname', + 'email' => 'Email', + 'created_at' => 'Registered', + 'last_seen' => 'Last seen', + 'is_guest' => 'Guest', + 'joined' => 'Joined', + 'is_online' => 'Online now', + 'is_offline' => 'Currently offline', + 'send_invite' => 'Send invitation by email', + 'send_invite_comment' => 'Sends a welcome message containing login and password information.', + 'create_password' => 'Create Password', + 'create_password_comment' => 'Enter a new password used for signing in.', + 'reset_password' => 'Reset Password', + 'reset_password_comment' => 'To reset this users password, enter a new password here.', + 'confirm_password' => 'Password Confirmation', + 'confirm_password_comment' => 'Enter the password again to confirm it.', + 'groups' => 'Groups', + 'empty_groups' => 'There are no user groups available.', + 'avatar' => 'Avatar', + 'details' => 'Details', + 'account' => 'Account', + 'block_mail' => 'Block all outgoing mail sent to this user.', + 'status_label' => 'Status', + 'status_guest' => 'Guest', + 'status_activated' => 'Activated', + 'status_registered' => 'Registered', + 'created_ip_address' => 'Created IP Address', + 'last_ip_address' => 'Last IP Address', + ], + 'group' => [ + 'label' => 'Group', + 'id' => 'ID', + 'name' => 'Name', + 'description_field' => 'Description', + 'code' => 'Code', + 'code_comment' => 'Enter a unique code used to identify this group.', + 'created_at' => 'Created', + 'users_count' => 'Users' + ], + 'groups' => [ + 'menu_label' => 'Groups', + 'all_groups' => 'User Groups', + 'new_group' => 'New Group', + 'delete_selected_confirm' => 'Do you really want to delete selected groups?', + 'list_title' => 'Manage Groups', + 'delete_confirm' => 'Do you really want to delete this group?', + 'delete_selected_success' => 'Successfully deleted the selected groups.', + 'delete_selected_empty' => 'There are no selected groups to delete.', + 'return_to_list' => 'Back to groups list', + 'return_to_users' => 'Back to users list', + 'create_title' => 'Create User Group', + 'update_title' => 'Edit User Group', + 'preview_title' => 'Preview User Group' + ], + 'login' => [ + 'attribute_email' => 'Email', + 'attribute_username' => 'Username' + ], + 'account' => [ + 'account' => 'Account', + 'account_desc' => 'User management form.', + 'banned' => 'Sorry, this user is currently not activated. Please contact us for further assistance.', + 'redirect_to' => 'Redirect to', + 'redirect_to_desc' => 'Page name to redirect to after update, sign in or registration.', + 'code_param' => 'Activation Code Param', + 'code_param_desc' => 'The page URL parameter used for the registration activation code', + 'force_secure' => 'Force secure protocol', + 'force_secure_desc' => 'Always redirect the URL with the HTTPS schema.', + 'invalid_user' => 'A user was not found with the given credentials.', + 'invalid_activation_code' => 'Invalid activation code supplied.', + 'invalid_deactivation_pass' => 'The password you entered was invalid.', + 'invalid_current_pass' => 'The current password you entered was invalid.', + 'success_activation' => 'Successfully activated your account.', + 'success_deactivation' => 'Successfully deactivated your account. Sorry to see you go!', + 'success_saved' => 'Settings successfully saved!', + 'login_first' => 'You must be logged in first!', + 'already_active' => 'Your account is already activated!', + 'activation_email_sent' => 'An activation email has been sent to your email address.', + 'activation_by_admin' => 'You have successfully registered. Your account is not yet active and must be approved by an administrator.', + 'registration_disabled' => 'Registrations are currently disabled.', + 'registration_throttled' => 'Registration is throttled. Please try again later.', + 'sign_in' => 'Sign in', + 'register' => 'Register', + 'full_name' => 'Full Name', + 'email' => 'Email', + 'password' => 'Password', + 'login' => 'Login', + 'new_password' => 'New Password', + 'new_password_confirm' => 'Confirm New Password', + 'update_requires_password' => 'Confirm password on update', + 'update_requires_password_comment' => 'Require the current password of the user when changing their profile.', + 'activation_page' => 'Activation Page', + 'activation_page_comment' => 'Select a page to use for activating the user account', + 'reset_page' => 'Reset Page', + 'reset_page_comment' => 'Select a page to use for resetting the account password', + ], + 'reset_password' => [ + 'reset_password' => 'Reset Password', + 'reset_password_desc' => 'Forgotten password form.', + 'code_param' => 'Reset Code Param', + 'code_param_desc' => 'The page URL parameter used for the reset code' + ], + 'session' => [ + 'session' => 'Session', + 'session_desc' => 'Adds the user session to a page and can restrict page access.', + 'security_title' => 'Allow only', + 'security_desc' => 'Who is allowed to access this page.', + 'all' => 'All', + 'users' => 'Users', + 'guests' => 'Guests', + 'allowed_groups_title' => 'Allow groups', + 'allowed_groups_description' => 'Choose allowed groups or none to allow all groups', + 'redirect_title' => 'Redirect to', + 'redirect_desc' => 'Page name to redirect if access is denied.', + 'logout' => 'You have been successfully logged out!', + 'stop_impersonate_success' => 'You are no longer impersonating a user.', + ] +]; diff --git a/plugins/rainlab/user/lang/es-ar/lang.php b/plugins/rainlab/user/lang/es-ar/lang.php new file mode 100644 index 0000000..40bf787 --- /dev/null +++ b/plugins/rainlab/user/lang/es-ar/lang.php @@ -0,0 +1,168 @@ + [ + 'name' => 'User', + 'description' => 'Front-end user management.', + 'tab' => 'Users', + 'access_users' => 'Administrar Usuarios', + 'access_groups' => 'Administrar Grupos de Usuarios', + 'access_settings' => 'Administrar Ajustes de Usuario' + ], + 'users' => [ + 'menu_label' => 'Usuarios', + 'all_users' => 'Todos los Usuarios', + 'new_user' => 'Nuevo Usuario', + 'list_title' => 'Administrar Usuarios', + 'activating' => 'Activando...', + 'trashed_hint_title' => 'El usuario ha desactivado su cuenta', + 'trashed_hint_desc' => 'Éste usuario ha desactivado su cuenta y no quiere volver a aparecer en el sitio. Ellos pueden restaurar su cuenta en cualquier momento al re-ingresar.', + 'banned_hint_title' => 'El usuario ha sido baneado', + 'banned_hint_desc' => 'Éste usuario ha sido baneado por un administrador y estará imposibilitado para ingresar.', + 'activate_warning_title' => 'El usuario no esta activado!', + 'activate_warning_desc' => 'Éste usuario no esta activado y quizá no pueda ingresar.', + 'activate_confirm' => 'Realmente desea activar éste usuario?', + 'activate_manually' => 'Activar éste usuario manualmente', + 'delete_confirm' => 'Realmente desea eliminar éste usuario?', + 'activated_success' => 'El usuario ha sido activado con éxito!', + 'return_to_list' => 'Regresar a la lista de usuarios', + 'delete_selected' => 'Eliminar seleccionados', + 'delete_selected_confirm' => 'Eliminar los usuarios seleccionados?', + 'delete_selected_empty' => 'No hay usuarios seleccionados para eliminar.', + 'delete_selected_success' => 'Los usuarios seleccionados se eliminaron con éxito.', + 'deactivate_selected' => 'Desactivar seleccionados', + 'deactivate_selected_confirm' => 'Desactivar los usuarios seleccionados?', + 'deactivate_selected_empty' => 'No hay usuarios seleccionados para desactivar.', + 'deactivate_selected_success' => 'Los usuarios seleccionados se desactivaron con éxito.', + 'restore_selected' => 'Reactivar seleccionados', + 'restore_selected_confirm' => 'Reactivar los usuarios seleccionados?', + 'restore_selected_empty' => 'No hay usuarios seleccionados para reactivar.', + 'restore_selected_success' => 'Los usuarios seleccionados se reactivaron con éxito.', + 'ban_selected' => 'Suspender seleccionados (Banear)', + 'ban_selected_confirm' => 'Suspender los usuarios seleccionados?', + 'ban_selected_empty' => 'No hay usuarios seleccionados para suspender.', + 'ban_selected_success' => 'Los usuarios seleccionados se suspendieron con éxito.', + 'unban_selected' => 'Reanudar seleccionados (Baneados)', + 'unban_selected_confirm' => 'Reanudar los usuarios seleccionados?', + 'unban_selected_empty' => 'No hay usuarios seleccionados para reanudar.', + 'unban_selected_success' => 'Los usuarios seleccionados se reanudaron con éxito.', + ], + 'settings' => [ + 'users' => 'Usuarios', + 'menu_label' => 'Ajustes de Usuario', + 'menu_description' => 'Administrar los ajustes de usuario.', + 'activation_tab' => 'Activación', + 'signin_tab' => 'Ingreso', + 'registration_tab' => 'Registración', + 'notifications_tab' => 'Notificaciones', + 'allow_registration' => 'Permitir registro de ususarios', + 'allow_registration_comment' => 'Si esta desactivado, los usuarios solo podrán ser creados por administradores.', + 'activate_mode' => 'Modo de Activación', + 'activate_mode_comment' => 'Seleccione la forma en que una cuenta debe ser activada.', + 'activate_mode_auto' => 'Automático', + 'activate_mode_auto_comment' => 'Se activa automáticamente en la registración.', + 'activate_mode_user' => 'Usuario', + 'activate_mode_user_comment' => 'El usuario activa su propia cuenta a través del e-mail.', + 'activate_mode_admin' => 'Administrador', + 'activate_mode_admin_comment' => 'Solo los administradores pueden activar usuarios.', + 'require_activation' => 'El ingreso requiere activación', + 'require_activation_comment' => 'Los usuarios necesitarán una cuenta activa para ingresar.', + 'use_throttle' => 'Regular intentos fallidos', + 'use_throttle_comment' => 'Repetidos intentos fallidos de ingreso suspenderán temporalmente al usuario.', + 'login_attribute' => 'Atributo para ingreso', + 'login_attribute_comment' => 'Seleccione que atributo sera utilizado para el ingreso.', + ], + 'user' => [ + 'label' => 'Usuario', + 'id' => 'ID', + 'username' => 'Nombre de Usuario', + 'name' => 'Nombre', + 'surname' => 'Apellido', + 'email' => 'Email', + 'created_at' => 'Registrado', + 'create_password' => 'Crear Contraseña', + 'create_password_comment' => 'Ingrese una nueva contraseña.', + 'reset_password' => 'Reiniciar contraseña ', + 'reset_password_comment' => 'Para reiniciar esta contraseña, ingrese un nueva aquí.', + 'confirm_password' => 'Confirmar contraseña', + 'confirm_password_comment' => 'Ingrese nuevamente la contraseña para confirmarla.', + 'groups' => 'Grupos', + 'empty_groups' => 'No hay grupos de usuarios disponibles.', + 'avatar' => 'Avatar', + 'details' => 'Detalles', + 'account' => 'Cuenta' + ], + 'group' => [ + 'label' => 'Grupo', + 'id' => 'ID', + 'name' => 'Nombre', + 'description_field' => 'Descripción', + 'code' => 'Código', + 'code_comment' => 'Ingrese un código único para identificar a este grupo.', + 'created_at' => 'Creado', + 'users_count' => 'Usuarios' + ], + 'groups' => [ + 'menu_label' => 'Grupos', + 'all_groups' => 'Grupos de Usuario', + 'new_group' => 'Nuevo Grupo', + 'delete_selected_confirm' => 'Realmente quiere eliminar los grupos seleccionados?', + 'list_title' => 'Administrar Grupos', + 'delete_confirm' => 'Realmente quiere eliminar este grupo?', + 'delete_selected_success' => 'Los grupos seleccionados se eliminaron con éxito.', + 'delete_selected_empty' => 'No hay grupos seleccionados para eliminar.', + 'return_to_list' => 'Volver a la lista de grupos', + 'return_to_users' => 'Volver a la lista de usuarios', + 'create_title' => 'Crear Grupo', + 'update_title' => 'Editar Grupo', + 'preview_title' => 'Ver Grupo' + ], + 'login' => [ + 'attribute_email' => 'Email', + 'attribute_username' => 'Nombre de Usuario' + ], + 'account' => [ + 'account' => 'Cuenta', + 'account_desc' => 'Formulario de administración de usuario.', + 'redirect_to' => 'Redirigir a', + 'redirect_to_desc' => 'Nombre de la página a redirigir luego de una actualización, ingreso o registro.', + 'code_param' => 'Parámetro del Código de Activación', + 'code_param_desc' => 'El parámetro de URL utilizado para el código de activación de registro.', + 'invalid_user' => 'No se encontraron usuarios con los datos proporcionados.', + 'invalid_activation_code' => 'Código de activación inválido.', + 'invalid_deactivation_pass' => 'La contraseña ingresada no es válida.', + 'success_activation' => 'Su cuenta fue activada con éxito.', + 'success_deactivation' => 'Su cuenta fue desactivada con éxito.', + 'success_saved' => 'Ajustes guardados con éxito!', + 'login_first' => 'Primero debes ingresar con un usuario!', + 'already_active' => 'Su cuenta ya se encuentra activada!', + 'activation_email_sent' => 'Un mail de activación fue enviado a su cuenta de correo.', + 'registration_disabled' => 'Actualmente los registros no están habilitados.', + 'sign_in' => 'Ingresar', + 'register' => 'Registrarse', + 'full_name' => 'Nombre Completo', + 'email' => 'Email', + 'password' => 'Contraseña', + 'login' => 'Iniciar Sesión', + 'new_password' => 'Nueva Contraseña', + 'new_password_confirm' => 'Confirmar Nueva Contraseña' + ], + 'reset_password' => [ + 'reset_password' => 'Reiniciar Contraseña', + 'reset_password_desc' => 'Formulario de olvido de contraseña.', + 'code_param' => 'Parámetro del Código de Reinicio', + 'code_param_desc' => 'El parámetro de URL utilizado para el código de reinicio.' + ], + 'session' => [ + 'session' => 'Sesión', + 'session_desc' => 'Agrega la sesión de usuario a una pagina y permite restringir el acceso a la misma.', + 'security_title' => 'Permitir acceso a', + 'security_desc' => 'Quien tiene permiso para acceder a esta página.', + 'all' => 'Todos', + 'users' => 'Usuarios', + 'guests' => 'Invitados', + 'redirect_title' => 'Redirigir a', + 'redirect_desc' => 'Nombre de la página a redirigir si el acceso es denegado.', + 'logout' => 'La sesión se ha cerrado con éxito!' + ] +]; diff --git a/plugins/rainlab/user/lang/es/lang.php b/plugins/rainlab/user/lang/es/lang.php new file mode 100644 index 0000000..360d73e --- /dev/null +++ b/plugins/rainlab/user/lang/es/lang.php @@ -0,0 +1,212 @@ + [ + 'name' => 'Usuarios', + 'description' => 'Administración de usuarios en la interfaz del sistema.', + 'tab' => 'Usuarios', + 'access_users' => 'Administrar usuarios', + 'access_groups' => 'Administrar grupos', + 'access_settings' => 'Preferencias de usuario', + 'impersonate_user' => 'Personificar Usuario' + ], + 'users' => [ + 'menu_label' => 'Usuarios', + 'all_users' => 'Todos los usuarios', + 'new_user' => 'Nuevo usuario', + 'list_title' => 'Administrar usuarios', + 'trashed_hint_title' => 'El usuario tiene su perfil desactivado', + 'trashed_hint_desc' => 'Este usuario tiene desactivado su perfil y no quiere aparecer en el sitio. Los usuarios pueden reactivar su perfil en cualquier momento iniciando sesión nuevamente.', + 'banned_hint_title' => 'El Usuario ha sido bloqueado', + 'banned_hint_desc' => 'Este usuario ha sido bloqueado por un administrador y no será capaz de iniciar sesión.', + 'guest_hint_title' => 'Este usuario es un invitado', + 'guest_hint_desc' => 'El usuario es almacenado sólo para efectos de referencia y necesita registrarse antes de iniciar sesión.', + 'activate_warning_title' => '¡El usuario no se pudo activar!', + 'activate_warning_desc' => 'Este usuario todavía no ha sido activado y no será capaz de iniciar sesión.', + 'activate_confirm' => '¿Realmente desea activar este usuario?', + 'activated_success' => '¡El usuario ha sido activado exitosamente!', + 'activate_manually' => 'Activar usuario manualmente', + 'convert_guest_confirm' => '¿Convertir este invitado en usuario?', + 'convert_guest_manually' => 'Convertir a usuario registrado', + 'convert_guest_success' => 'El usuario ha sido convertido a una cuenta registrada', + 'impersonate_user' => 'Iniciar sesión como este usuario', + 'impersonate_confirm' => '¿Estás seguro que quieres iniciar sesión como este usuario? Puedes volver a tu estado original cerrando la sesión.', + 'impersonate_success' => 'Has iniciado sesión como este usuario correctamente.', + 'delete_confirm' => '¿Realmente desea eliminar este usuario?', + 'unban_user' => 'Desbloquear este usuario', + 'unban_confirm' => '¿Realmente desea desbloquear este usuario?', + 'unbanned_success' => 'El usuario ha sido desbloqueado', + 'return_to_list' => 'Volver a la lista de usuarios', + 'update_details' => 'Actualizar detalles', + 'bulk_actions' => 'Acciones en masa', + 'delete_selected' => 'Eliminar usuarios seleccionados', + 'delete_selected_confirm' => '¿Eliminar los usuarios seleccionados?', + 'delete_selected_empty' => 'No hay usuarios seleccionados a eliminar.', + 'delete_selected_success' => 'Se eliminaron exitosamente los usuarios seleccionados.', + 'activate_selected' => 'Activar usuarios seleccionados', + 'activate_selected_confirm' => '¿Activar los usuarios seleccionados?', + 'activate_selected_empty' => 'No hay usuarios seleccionados para activar.', + 'activate_selected_success' => 'Los usuarios seleccionados han sido activados exitosamente.', + 'deactivate_selected' => 'Desactivar usuarios seleccionados', + 'deactivate_selected_confirm' => '¿Desactivar los usuarios seleccionados?', + 'deactivate_selected_empty' => 'No hay usuarios seleccionados a desactivar.', + 'deactivate_selected_success' => 'Se desactivaron exitosamente los usuarios seleccionados.', + 'restore_selected' => 'Restablecer los usuarios seleccionados', + 'restore_selected_confirm' => '¿Restablecer los usuarios seleccionados?', + 'restore_selected_empty' => 'No hay usuarios seleccionados a restablecer.', + 'restore_selected_success' => 'Se restablecieron exitosamente los usuarios seleccionados.', + 'ban_selected' => 'Bloquear usuarios seleccionados', + 'ban_selected_confirm' => '¿Bloquear los usuarios seleccionados?', + 'ban_selected_empty' => 'No hay usuarios seleccionados a bloquear.', + 'ban_selected_success' => 'Se bloquearon exitosamente los usuarios seleccionados.', + 'unban_selected' => 'Desbloquear usuarios seleccionados', + 'unban_selected_confirm' => '¿Desbloquear los usuarios seleccionados?', + 'unban_selected_empty' => 'No hay usuarios seleccionados a desbloquear.', + 'unban_selected_success' => 'Se desbloquearon exitosamente los usuarios seleccionados.', + ], + 'settings' => [ + 'users' => 'Usuarios', + 'menu_label' => 'Preferencias de usuario', + 'menu_description' => 'Administra las preferencias de los usuarios.', + 'activation_tab' => 'Activación', + 'signin_tab' => 'Iniciar sesión', + 'registration_tab' => 'Registro', + 'notifications_tab' => 'Notificaciones', + 'allow_registration' => 'Permitir registro de usuarios', + 'allow_registration_comment' => 'Si está deshabilitado los usuarios sólo pueden ser creados por administradores.', + 'min_password_length' => 'Largo mínimo de la contraseña', + 'min_password_length_comment' => 'La cantidad mínima de caracteres requerida para contraseñas.', + 'activate_mode' => 'Modo de activación', + 'activate_mode_comment' => 'Seleccione como debería ser activado un perfil de usuario.', + 'activate_mode_auto' => 'Automática', + 'activate_mode_auto_comment' => 'Activada automáticamente al registrarse.', + 'activate_mode_user' => 'Usuario', + 'activate_mode_user_comment' => 'El usuario activa su perfil usando su e-mail.', + 'activate_mode_admin' => 'Administrador', + 'activate_mode_admin_comment' => 'Sólo un administrador puede activar un usuario.', + 'require_activation' => 'Inicio de sesión requiere activación.', + 'require_activation_comment' => 'Usuarios deben tener una perfil activado para poder iniciar sesión.', + 'use_throttle' => 'Límite de intentos', + 'use_throttle_comment' => 'Intentos de inicios de sesión seguidos que provocaran la suspensión temporal del perfil de usuario.', + 'block_persistence' => 'Prevenir sesiones concurrentes', + 'block_persistence_comment' => 'Prevenir que los usuarios habilitados puedan iniciar sesión desde múltiples dispositivos.', + 'login_attribute' => 'Atributo de inicio de sesión', + 'login_attribute_comment' => 'Seleccione que dato de usuario debería ser utilizado para el inicio de sesión.', + 'remember_login' => 'Modo recordar usuario', + 'remember_login_comment' => 'Selecciona si la sesión del usuario debe ser persistente.', + 'remember_always' => 'Siempre', + 'remember_never' => 'Nunca', + 'remember_ask' => 'Preguntar al usuario al iniciar sesión', + ], + 'user' => [ + 'label' => 'Usuario', + 'id' => 'ID', + 'username' => 'Nombre de usuario', + 'name' => 'Nombres', + 'name_empty' => 'Anónimo', + 'surname' => 'Apellidos', + 'email' => 'E-mail', + 'created_at' => 'Registrado', + 'last_seen' => 'Última vez visto', + 'is_guest' => 'Invitado', + 'joined' => 'Incorporado', + 'is_online' => 'En línea ahora', + 'is_offline' => 'Actualmente desconectado', + 'send_invite' => 'Enviar invitación por email', + 'send_invite_comment' => 'Envía un mensaje de bienvenida con información de inicio de sesión y contraseña.', + 'create_password' => 'Crear contraseña', + 'create_password_comment' => 'Ingrese nueva contraseña para iniciar sesión', + 'reset_password' => 'Restablecer contraseña', + 'reset_password_comment' => 'Para restablecer la contraseña del usuario, ingrese una nueva contraseña aquí.', + 'confirm_password' => 'Confirmación de contraseña', + 'confirm_password_comment' => 'Ingrese la contraseña nuevamente para confirmarla.', + 'groups' => 'Grupos', + 'empty_groups' => 'No hay grupos de usuarios disponibles.', + 'avatar' => 'Avatar', + 'details' => 'Detalles', + 'account' => 'Perfil', + 'block_mail' => 'Bloquear todos los envios de e-mail para este usuario.', + 'status_guest' => 'Invitado', + 'status_activated' => 'Activado', + 'status_registered' => 'Registrado', + ], + 'group' => [ + 'label' => 'Grupo', + 'id' => 'ID', + 'name' => 'Nombre', + 'description_field' => 'Descripción', + 'code' => 'Código', + 'code_comment' => 'Ingrese un código único para identificar este grupo.', + 'created_at' => 'Creado', + 'users_count' => 'Usuarios' + ], + 'groups' => [ + 'menu_label' => 'Grupos', + 'all_groups' => 'Grupos de usuarios', + 'new_group' => 'Nuevo grupo', + 'delete_selected_confirm' => '¿Realmente quiere eliminar todos los grupos seleccionados?', + 'list_title' => 'Administrar grupos', + 'delete_confirm' => '¿Realmente desea eliminar este grupo?', + 'delete_selected_success' => 'Los grupos seleccionados fueron eliminados exitosamente.', + 'delete_selected_empty' => 'No hay grupos seleccionados para eliminar.', + 'return_to_list' => 'Volver a la lista de grupos', + 'return_to_users' => 'Volver a la lista de usuarios', + 'create_title' => 'Añadir grupo', + 'update_title' => 'Editar grupo', + 'preview_title' => 'Vista previa de grupo' + ], + 'login' => [ + 'attribute_email' => 'Email', + 'attribute_username' => 'Nombre de usuario' + ], + 'account' => [ + 'account' => 'Perfil', + 'account_desc' => 'Formulario para gestionar datos del usuario.', + 'banned' => 'Los sentimos, este usuario no se encuentra activado actualmente. Por favor contáctanos para mayor asistencia.', + 'redirect_to' => 'redirigir a', + 'redirect_to_desc' => 'Página hacia la cual redirigir despues de una actualización, inicio de sesión o registro.', + 'code_param' => 'Parámetro para el código de activación', + 'code_param_desc' => 'El parámetro de URL en la página usuado para el código de activación del registro.', + 'force_secure' => 'Forzar protocolo seguro', + 'force_secure_desc' => 'Siempre redirigir la URL utilizando HTTPS.', + 'invalid_user' => 'No se encontro un usuario con las credenciales proporcionadas.', + 'invalid_activation_code' => 'El código de activación que proporcionó es inválido.', + 'invalid_deactivation_pass' => 'La contraseña que ingresó es inválida.', + 'success_activation' => 'Su perfil fue activado exitosamente.', + 'success_deactivation' => 'Su perfil fue desactivado exitosamente. ¡Nos apena mucho su partida!', + 'success_saved' => '¡Preferencias guardadas exitosamente!', + 'login_first' => '¡Debe iniciar sesión primero!', + 'already_active' => '¡Su perfil ya estaba activado!', + 'activation_email_sent' => 'Un e-mail de confirmación ha sido enviado a su dirección de correo electrónico.', + 'registration_disabled' => 'El registro de usuarios está temporalmente deshabilitado.', + 'sign_in' => 'Iniciar sesión', + 'register' => 'Registro', + 'full_name' => 'Nombre completo', + 'email' => 'E-mail', + 'password' => 'Contraseña', + 'login' => 'Iniciar sesión', + 'new_password' => 'Nueva contraseña', + 'new_password_confirm' => 'Confirme su nueva contraseña' + ], + 'reset_password' => [ + 'reset_password' => 'Restablecer contraseña', + 'reset_password_desc' => 'Formulario de contraseña olvidada.', + 'code_param' => 'Parámetro para el código de restablecimiento', + 'code_param_desc' => 'El parámetro de URL de la página usado para el código de restablecimiento.e' + ], + 'session' => [ + 'session' => 'Sesión', + 'session_desc' => 'Agrega la sesión del usuario a una página y puede restringir el acceso a dicha página.', + 'security_title' => 'Permitir solamente', + 'security_desc' => 'Quién es permitido acceder a esta página.', + 'all' => 'Todos', + 'users' => 'Usuarios', + 'guests' => 'Invitados', + 'allowed_groups_title' => 'Permitir grupos', + 'allowed_groups_description' => 'Selecciona los grupos permitidos o ninguno para permitir todos los grupos', + 'redirect_title' => 'redirigir a', + 'redirect_desc' => 'Página a la cual redirigir si el acceso es denegado.', + 'logout' => '¡Ha terminado exitosamente su sesión!', + 'stop_impersonate_success' => 'Has dejado de personificar al usuario.', + ] +]; diff --git a/plugins/rainlab/user/lang/fa/lang.php b/plugins/rainlab/user/lang/fa/lang.php new file mode 100644 index 0000000..8b2b2f0 --- /dev/null +++ b/plugins/rainlab/user/lang/fa/lang.php @@ -0,0 +1,191 @@ + [ + 'name' => 'کاربر', + 'description' => 'مدیریت کاربران', + 'tab' => 'کاربران', + 'access_users' => 'مدیریت کاربران', + 'access_groups' => 'مدیریت گروه‌های کاربران', + 'access_settings' => 'مدیریت تنطیمات کاربران', + 'impersonate_user' => 'از دید کاربران' + ], + 'users' => [ + 'menu_label' => 'کاربران', + 'all_users' => 'همه کاربران', + 'new_user' => 'کاربر جدید', + 'list_title' => 'مدیریت کاربران', + 'trashed_hint_title' => 'کاربر حساب خود را غیر ÙØ¹Ø§Ù„ کرده است', + 'trashed_hint_desc' => 'این کاربر حساب خود را غیر ÙØ¹Ø§Ù„ کرده است Ùˆ علاقه ای به ادامه ÙØ¹Ø§Ù„یت در سایت را ندارد. کاربران با ورود مجدد به سایت میتوانند حساب خود را ÙØ¹Ø§Ù„ کنند.', + 'banned_hint_title' => 'حساب کاربری مسدود است', + 'banned_hint_desc' => 'حساب این کاربر توسط مدیر مسدود است Ùˆ نمی تواند به سیستم وارد شود', + 'guest_hint_title' => 'این کاربر مهمان است', + 'guest_hint_desc' => 'این کاربر برای مرجع دهی ثبت شده است باید ثبت نام Ùˆ وارد سیستم شود.', + 'activate_warning_title' => 'کاربر ÙØ¹Ø§Ù„ نمیباشد!', + 'activate_warning_desc' => 'این کاربر ÙØ¹Ø§Ù„ نشده است Ùˆ نمیتواند وارد سایت شود.', + 'activate_confirm' => 'آیا از ÙØ¹Ø§Ù„سازی این کاربر اطمینان دارید؟', + 'activated_success' => 'کاربر با موÙقیت ÙØ¹Ø§Ù„ شد.', + 'activate_manually' => 'ÙØ¹Ø§Ù„ سازی دستی این کاربر', + 'convert_guest_confirm' => 'تبدیل این کاربر به مهمان؟', + 'convert_guest_manually' => 'تبدیل به کاربر ثبت نام شده', + 'convert_guest_success' => 'کارب به حالت ثبت نام شده تغییر پیدا کرد', + 'delete_confirm' => 'آیا از حذ٠این کاربر اطمینان دارید؟', + 'unban_user' => 'Ø±ÙØ¹ انتسداد حساب کاربری', + 'unban_confirm' => 'آیا از Ø±ÙØ¹ انسداد حساب کاربری این شخص اطمینان دارید؟', + 'unbanned_success' => 'حساب کاربری Ø±ÙØ¹ انسداد شد', + 'return_to_list' => 'بازگشت به لیست کاربران', + 'update_details' => 'ویرایش جزئیات', + 'bulk_actions' => 'اعمال گروهی', + 'delete_selected' => 'حذ٠انتخاب شده', + 'delete_selected_confirm' => 'آیا از حذ٠کاربران انتخاب شده اطمینان داری؟', + 'delete_selected_empty' => 'کاربری جهت حذ٠انتخاب نشده است.', + 'delete_selected_success' => 'کاربران انتخاب شده با موÙقیت حذ٠شدند.', + 'deactivate_selected' => 'غیر ÙØ¹Ø§Ù„ سازی انتخاب شده', + 'deactivate_selected_confirm' => 'کاربران انتخاب شده ØºÛŒØ±ÙØ¹Ø§Ù„ شوند؟', + 'deactivate_selected_empty' => 'کاربری برای غیر ÙØ¹Ø§Ù„ سازی انتخاب نشده است', + 'deactivate_selected_success' => 'کاربران انتخاب شده با موÙقیت ØºÛŒØ±ÙØ¹Ø§Ù„ شدند', + 'restore_selected' => 'بازسازی انتخاب شده ها', + 'restore_selected_confirm' => 'کاربرانت انتخاب شده بازسازی شوند؟', + 'restore_selected_empty' => 'کاربری برای بازسازی انتخاب نشده', + 'restore_selected_success' => 'کاربران انتخاب شده با موÙقیت بازسازی شدند', + 'ban_selected' => 'مسدود کردن انتخاب شده ها', + 'ban_selected_confirm' => 'کاربران انتخاب شده مسدود شوند؟', + 'ban_selected_empty' => 'کاربری برای اسنداد حساب انتخاب نشده است', + 'ban_selected_success' => 'حساب کاربران انتخاب شده با موÙقیت مسدود شد', + 'unban_selected' => 'Ø±ÙØ¹ انسداد انتخاب شده ها', + 'unban_selected_confirm' => 'کاربران انتخاب شده Ø±ÙØ¹ انسداد شوند؟', + 'unban_selected_empty' => 'کاربری برای Ø±ÙØ¹ انسداد انتخاب نشده است', + 'unban_selected_success' => 'کاربران انتخاب شده با موÙقیت Ø±ÙØ¹ انسداد شدند', + 'activating' => 'ÙØ¹Ø§Ù„ سازی...', + ], + 'settings' => [ + 'users' => 'کاربران', + 'menu_label' => 'تنظیمات کاربران', + 'menu_description' => 'مدیریت تنظیمات مربوط به کاربر.', + 'activation_tab' => 'ÙØ¹Ø§Ù„ سازی', + 'signin_tab' => 'ورود', + 'registration_tab' => 'ایجاد حساب کاربری', + 'notifications_tab' => 'هشدار ها', + 'allow_registration' => 'به کاربران اجازه ثبت نام داده شود.', + 'allow_registration_comment' => 'اگر این گزینه غیر ÙØ¹Ø§Ù„ باشد حساب کاربری Ùقط توسط مدیران میتواند ایجاد شود.', + 'activate_mode' => 'روش ÙØ¹Ø§Ù„ سازی', + 'activate_mode_comment' => 'روشی را Ú©Ù‡ میخواهید حساب های کاربری از آن طریق ÙØ¹Ø§Ù„ شوند را انتخاب نمایید.', + 'activate_mode_auto' => 'خودکار', + 'activate_mode_auto_comment' => 'بهنگام ثبت نام حساب کاربری به صورت خودکار ÙØ¹Ø§Ù„ شود.', + 'activate_mode_user' => 'کاربر', + 'activate_mode_user_comment' => 'کاربران حساب خود را از طریق ایمیل ÙØ¹Ø§Ù„ نمایند.', + 'activate_mode_admin' => 'مدیریت', + 'activate_mode_admin_comment' => 'Ùقط مدیران حساب کاربری را ÙØ¹Ø§Ù„ نمایید.', + 'require_activation' => 'ورود نیاز مند ÙØ¹Ø§Ù„ سازی حساب کاربری Ù…ÛŒ باشد', + 'require_activation_comment' => 'کاربران باید دارای حساب کاربری ÙØ¹Ø§Ù„ جهت ورود باشند.', + 'use_throttle' => 'جلو گیری از ورود', + 'use_throttle_comment' => 'تکرار ورود نا موÙÙ‚ کاربر را به طور موقت غیر ÙØ¹Ø§Ù„ میکند.', + 'login_attribute' => 'مشخصه ÛŒ ورود', + 'login_attribute_comment' => 'مشخصه ای را Ú©Ù‡ کاربر برای ورود باید وارد نماید انتخاب نمایید.', + ], + 'user' => [ + 'label' => 'کاربر', + 'id' => 'مشخصه', + 'username' => 'نام کاربری', + 'name' => 'نام', + 'name_empty' => 'ناشناس', + 'surname' => 'نام خانوادگی', + 'email' => 'پست الکترونیکی', + 'created_at' => 'تاریخ ثبت نام', + 'last_seen' => 'آخرین بازدید', + 'is_guest' => 'مهمان', + 'joined' => 'عضو شده', + 'is_online' => 'آنلاین', + 'is_offline' => 'هم اکنون Ø¢Ùلاین', + 'send_invite' => 'ارسال دعوت نامه با ایمیل', + 'send_invite_comment' => 'ارسال ایمیل خوش آمد شامل رمز عبور Ùˆ نام کاربری', + 'create_password' => 'ساخت رمزعبور', + 'create_password_comment' => 'رمز جدید برای Ø§Ø³ØªÙØ§Ø¯Ù‡ کاربر در زمان ورود را وارد کنید', + 'reset_password' => 'تنظیم مجدد کلمه عبور', + 'reset_password_comment' => 'جهت تنظیم مجدد کلمه عبور کاربر ØŒ کلمه عبور جدید را وارد نمایید.', + 'confirm_password' => 'تایید کلمه عبور', + 'confirm_password_comment' => 'جهت تایید کلمه عبور را مجددا وارد نمایید.', + 'groups' => 'گرو ها', + 'empty_groups' => 'گروه کاربری موجود نیست', + 'avatar' => 'نمایه', + 'details' => 'جزییات', + 'account' => 'حساب کاربری', + 'block_mail' => 'هیچ ایمیلی به این کاربر ارسال نشود', + 'status_guest' => 'مهمان', + 'status_activated' => 'ÙØ¹Ø§Ù„', + 'status_registered' => 'عضو شده', + 'user' => 'user', + ], + 'group' => [ + 'label' => 'گروه', + 'id' => 'مشخصه', + 'name' => 'نام', + 'description_field' => 'توضیحات', + 'code' => 'کد یکتا', + 'code_comment' => 'کد یکتایی را جهت دسترسی به این گروه وارد نمایید', + 'created_at' => 'تاریخ ایجاد', + 'users_count' => 'کاربران', + ], + 'groups' => [ + 'menu_label' => 'گروه ها', + 'all_groups' => 'گروه های کاربر', + 'new_group' => 'گروه جدید', + 'delete_selected_confirm' => 'آیا از حذ٠گروه های انتخاب شده اطمینان دارید؟', + 'list_title' => 'مدیریت گروه ها', + 'delete_confirm' => 'آیا از حذ٠این گروه اطمینان دارید؟', + 'delete_selected_success' => 'گروه های انتخاب شده با موÙقیت حذ٠شدند.', + 'delete_selected_empty' => 'گروهی جهت حذ٠انتخاب نشده است.', + 'return_to_list' => 'بازگشت به لیست گروه ها', + 'return_to_users' => 'بازگشت به لیست کاربران', + 'create_title' => 'ایجاد گروه کاربری جدید', + 'update_title' => 'ویرایش گروه کاربری', + 'preview_title' => 'پیش نمایش گروه کاربری', + ], + 'login' => [ + 'attribute_email' => 'پست الکترونیکی', + 'attribute_username' => 'نام کاربری', + ], + 'account' => [ + 'account' => 'حساب کاربری', + 'account_desc' => 'ÙØ±Ù… مدیریت کاربران.', + 'redirect_to' => 'انتقال به', + 'redirect_to_desc' => 'نام ØµÙØ­Ù‡ ای Ú©Ù‡ کاربر پس از ورود باید به آن ØµÙØ­Ù‡ منتقل شود.', + 'code_param' => 'پارامتر کد ÙØ¹Ø§Ù„ سازی', + 'code_param_desc' => 'پارامتر آدرس ØµÙØ­Ù‡ جهت Ø§Ø³ØªÙØ§Ø¯Ù‡ در کد ÙØ¹Ø§Ù„ سازی بهنگام ثبت نام', + 'invalid_user' => 'کاربری با اطلاعات وارد شده ÛŒØ§ÙØª نشد.', + 'invalid_activation_code' => 'مد ÙØ¹Ø§Ù„سازی معتبر نمیباشد', + 'invalid_deactivation_pass' => 'کلمه عبور وارد شده صحیح نمی باشد.', + 'success_activation' => 'حساب کاربری شما با موÙقیت ÙØ¹Ø§Ù„ شد.', + 'success_deactivation' => 'حساب شما با موÙقیت غیر ÙØ¹Ø§Ù„ شد. از Ø±ÙØªÙ† شما متاسÙیم.', + 'success_saved' => 'تنظیمات با موÙقیت اعمال شدند.', + 'login_first' => 'شما باید وارد حساب کاربری خود شوید!', + 'already_active' => 'حساب کاربری شما قبلا ÙØ¹Ø§Ù„ شده است!', + 'activation_email_sent' => 'یک پست الکترونیکی حاوی آدرس ÙØ¹Ø§Ù„ سازی به ایمیل شما ارسال شد.', + 'registration_disabled' => 'در حال حاظر سرویس ثبت نام ÙØ¹Ø§Ù„ نمی باشد.', + 'sign_in' => 'ورود', + 'register' => 'ثبت نام', + 'full_name' => 'نام کامل', + 'email' => 'پست الکترونیکی', + 'password' => 'کلمه عبور', + 'login' => 'نام کاربری', + 'new_password' => 'کلمه عبور جدید', + 'new_password_confirm' => 'تایید کلمه عبور', + ], + 'reset_password' => [ + 'reset_password' => 'بازنشانی کلمه عبور', + 'reset_password_desc' => 'ÙØ±Ù… کلمه عبور ÙØ±Ø§Ù…وش شده.', + 'code_param' => 'پارامتر کد بازنشانی', + 'code_param_desc' => 'پارامتر آدرس ØµÙØ­Ù‡ ای Ú©Ù‡ جهت کد بازنشانی Ø§Ø³ØªÙØ§Ø¯Ù‡ خوهد شد', + ], + 'session' => [ + 'session' => 'جلسه', + 'session_desc' => 'جلسه کاربری را به ØµÙØ­Ù‡ جهت دسترسی کاربران اضاÙÙ‡ Ù…ÛŒ کند.', + 'security_title' => 'دسترسی برای', + 'security_desc' => 'Ú†Ù‡ کسانی میتوانند به این ØµÙØ­Ù‡ دسترسی داشته باشند؟', + 'all' => 'همه', + 'users' => 'کاربران', + 'guests' => 'میهمان ها', + 'redirect_title' => 'انتقال به', + 'redirect_desc' => 'نام ØµÙØ­Ù‡â€ŒØ§ÛŒ Ú©Ù‡ در صورت عدم اجازه دسترسی کاربر به آن انتقال پیدا می‌کند.', + 'logout' => 'با موÙقیت از سیستم خارج شدید!', + 'stop_impersonate_success' => 'دیگر در نقش٠سایر کاربران نیستید.', + ], +]; diff --git a/plugins/rainlab/user/lang/fr/lang.php b/plugins/rainlab/user/lang/fr/lang.php new file mode 100644 index 0000000..9e32168 --- /dev/null +++ b/plugins/rainlab/user/lang/fr/lang.php @@ -0,0 +1,206 @@ + [ + 'name' => 'Utilisateur', + 'description' => 'Gestion des utilisateurs Front-End.', + 'tab' => 'Utilisateur', + 'access_users' => 'Gérer les utilisateurs', + 'access_groups' => 'Gérer les groupes', + 'access_settings' => 'Gérer les paramètres', + 'impersonate_user' => 'Usurper l\'identité des utilisateurs' + ], + 'users' => [ + 'menu_label' => 'Utilisateurs', + 'all_users' => 'Tous les utilisateurs', + 'new_user' => 'Nouvel utilisateur', + 'list_title' => 'Gestion des utilisateurs', + 'trashed_hint_title' => 'L’utilisateur a désactivé son compte', + 'trashed_hint_desc' => 'Cet utilisateur a désactivé son compte ou ne souhaite plus apparaître sur le site. Il peut réactiver son compte à tout moment en se réinscrivant.', + 'banned_hint_title' => 'L’utilisateur a été banni', + 'banned_hint_desc' => 'Cet utilisateur a été banni par l’administrateur et ne pourra plus se réinscrire.', + 'guest_hint_title' => 'Ceci est un utilisteur invité', + 'guest_hint_desc' => 'Cette utilisateur est enregistré comme référence seulement, il doit s\'inscire avant de se connecter.', + 'activate_warning_title' => 'L’utilisateur n’est pas activé !', + 'activate_warning_desc' => 'Cet utilisateur n’a pas été activé et sera dans l’impossibilité de se connecter.', + 'activate_confirm' => 'Confirmez-vous l’activation de cet utilisateur ?', + 'activated_success' => 'L’utilisateur a été activé avec succès !', + 'activate_manually' => 'Activer cet utilisateur manuellement', + 'convert_guest_confirm' => 'Convertir cet invité en utilisateur?', + 'convert_guest_manually' => 'Convertir en utilisateur enregistré', + 'convert_guest_success' => 'L\'utilisateur à été converti en compte enregistré', + 'impersonate_user' => 'Usurper l\'identité d\'un utilisateur', + 'impersonate_confirm' => 'Usurper l\'identité de cet utilisateur? Vous pouvez revenir à votre état d\'origine en vous déconnectant.', + 'impersonate_success' => 'Vous êtes en train d\'usurper l\'identité de cet utilisateur', + 'delete_confirm' => 'Confirmez-vous la suppression de cet utilisateur ?', + 'unban_user' => 'Lever le bannissement de cet utilisateur', + 'unban_confirm' => 'Confirmez-vous la levée du bannissement de cet utilisateur ?', + 'unbanned_success' => 'L’utilisateur n’est plus banni', + 'return_to_list' => 'Retour à la liste des utilisateurs', + 'update_details' => 'Mettre à jour les informations', + 'bulk_actions' => 'Actions groupées', + 'delete_selected' => 'Supprimer la sélection', + 'delete_selected_confirm' => 'Supprimer les utilisateurs sélectionnés ?', + 'delete_selected_empty' => 'Aucun utilisateur n’a été sélectionné pour la suppression.', + 'delete_selected_success' => 'Les utilisateurs sélectionnés ont été supprimés correctement.', + 'activate_selected' => 'Activer la sélection', + 'activate_selected_confirm' => 'Activer les utilisateurs sélectionnés?', + 'activate_selected_empty' => 'Aucun utilisateur sélectionné à activer.', + 'activate_selected_success' => 'Les utilisateurs sélectionnés ont été activé avec succès.', + 'deactivate_selected' => 'Désactiver la sélection', + 'deactivate_selected_confirm' => 'Désactiver les utilisateurs sélectionnés ?', + 'deactivate_selected_empty' => 'Il n’y a aucun utilisateur sélectionné à désactiver.', + 'deactivate_selected_success' => 'Les utilisateurs sélectionnés ont été désactivés avec succès.', + 'restore_selected' => 'Activer la sélection', + 'restore_selected_confirm' => 'Activer les utilisateurs sélectionnés ?', + 'restore_selected_empty' => 'Il n’y a aucun utilisateur sélectionné à activer.', + 'restore_selected_success' => 'Les utilisateurs sélectionnés ont été activés avec succès.', + 'ban_selected' => 'Bannir la sélection', + 'ban_selected_confirm' => 'Bannir les utilisateurs sélectionnés ?', + 'ban_selected_empty' => 'Il n’y a aucun utilisateur sélectionné à bannir.', + 'ban_selected_success' => 'Les utilisateurs sélectionnés ont été bannis avec succès.', + 'unban_selected' => 'Lever le bannissement de la sélection', + 'unban_selected_confirm' => 'Lever le bannissement des utilisateurs sélectionnés ?', + 'unban_selected_empty' => 'Il n’y a aucun utilisateur sélectionné pour lesquels lever le bannissement.', + 'unban_selected_success' => 'Le bannissement des utilisateurs sélectionnés a été levé avec succès.', + ], + 'settings' => [ + 'users' => 'Utilisateurs', + 'menu_label' => 'Paramètres utilisateurs', + 'menu_description' => 'Gérer les paramètres liés aux utilisateurs.', + 'activation_tab' => 'Activation', + 'signin_tab' => 'Connexion', + 'registration_tab' => 'Enregistrement', + 'notifications_tab' => 'Notifications', + 'allow_registration' => 'Autoriser l\'inscription des utilisateurs', + 'allow_registration_comment' => 'Si désactivé, les utilisateurs ne peuvent être créés que par des administrateurs.', + 'activate_mode' => 'Mode d’activation', + 'activate_mode_comment' => 'Choisissez la méthode d’activation des comptes d’utilisateurs.', + 'activate_mode_auto' => 'Automatique', + 'activate_mode_auto_comment' => 'Activation automatique après inscription.', + 'activate_mode_user' => 'Utilisateur', + 'activate_mode_user_comment' => 'L’utilisateur active son compte par email.', + 'activate_mode_admin' => 'Administrateur', + 'activate_mode_admin_comment' => 'Seul un administrateur peut activer un utilisateur.', + 'require_activation' => 'Vérifier l’activation des comptes utilisateurs lors de la connexion', + 'require_activation_comment' => 'Si activé, les utilisateurs doivent avoir leur compte activé pour pouvoir se connecter.', + 'use_throttle' => 'Tentatives de connexion ratées', + 'use_throttle_comment' => 'En cas de tentatives répétées de connexion, l’utilisateur sera suspendu temporairement.', + 'block_persistence' => 'Empêcher les sessions simultanées', + 'block_persistence_comment' => 'Lorsque activée, les utilisateurs ne peuvent pas se connecter à plusieurs appareils en même temps.', + 'login_attribute' => 'Attribut pour l’identifiant', + 'login_attribute_comment' => 'Choisissez l’attribut utilisateur à utiliser comme identifiant.', + ], + 'user' => [ + 'label' => 'Utilisateur', + 'id' => 'ID', + 'username' => 'Identifiant', + 'name' => 'Prénom', + 'name_empty' => 'Anonyme', + 'surname' => 'Nom', + 'email' => 'E-mail', + 'created_at' => 'Enregistré le', + 'last_seen' => 'Dernière connexion', + 'is_guest' => 'Invité', + 'joined' => 'Inscrit le', + 'is_online' => 'Est actuellement connecté', + 'is_offline' => 'N’est pas connecté', + 'send_invite' => 'Envoyer une invitation par email', + 'send_invite_comment' => 'Envoie un message de bienvenue contenant les informations de connexion et de mot de passe.', + 'create_password' => 'Créer un mot de passe', + 'create_password_comment' => 'Entrez un nouveau mot de passe de connexion.', + 'reset_password' => 'Réinitialiser le mot de passe', + 'reset_password_comment' => 'Pour effacer le mot de passe de cet utilisateur, entrez un nouveau mot de passe ici.', + 'confirm_password' => 'Confirmation du mot de passe', + 'confirm_password_comment' => 'Entrez à nouveau le mot de passe pour le confirmer.', + 'groups' => 'Groupes', + 'empty_groups' => 'Aucun groupe d\'utilisateurs disponible.', + 'avatar' => 'Avatar', + 'details' => 'Détails', + 'account' => 'Compte', + 'block_mail' => 'Bloquer tous les e-mails sortants à destination de cet utilisateur.', + 'status_guest' => 'Invité', + 'status_activated' => 'Activé', + 'status_registered' => 'Enregistré', + ], + 'group' => [ + 'label' => 'Groupe d’utilisateurs', + 'id' => 'ID', + 'name' => 'Nom', + 'description_field' => 'Description', + 'code' => 'Code', + 'code_comment' => 'Entrez un code unique pour y accéder via l’API', + 'created_at' => 'Créé le', + 'users_count' => 'Nombre d’utilisateurs', + ], + 'groups' => [ + 'menu_label' => 'Groupes', + 'all_groups' => 'Tous les groupes', + 'new_group' => 'Nouveau groupe', + 'delete_selected_confirm' => 'Confirmez-vous la suppression des groupes sélectionnés ?', + 'list_title' => 'Groupes d’utilisateurs', + 'delete_confirm' => 'Confirmez-vous la suppression de ce groupe d’utilisateurs ?', + 'delete_selected_success' => 'Les groupes d’utilisateurs sélectionnés ont été supprimés avec succès.', + 'delete_selected_empty' => 'Il n’a aucun groupe d’utilisateurs sélectionné à supprimer.', + 'return_to_list' => 'Retour à la liste des groupes', + 'return_to_users' => 'Retour à la liste des utilisateurs', + 'create_title' => 'Nouveau groupe d’utilisateurs', + 'update_title' => 'Modifier un groupe d’utilisateurs', + 'preview_title' => 'Visualiser le groupe d\'utilisateurs', + ], + 'login' => [ + 'attribute_email' => 'Email', + 'attribute_username' => 'Pseudo', + ], + 'account' => [ + 'account' => 'Compte', + 'account_desc' => 'Gestion du compte utilisateur.', + 'banned' => 'Désolé, cet utilisateur n\'est actuellement pas activé. S\'il vous plaît contactez-nous pour plus d\'aide.', + 'redirect_to' => 'Rediriger vers', + 'redirect_to_desc' => 'Nom de la page de redirection après la mise à jour, la connexion ou l’enregistrement.', + 'code_param' => 'Paramètre code d’activation', + 'code_param_desc' => 'URL de la page utilisée pour l’enregistrement du code d’activation', + 'force_secure' => 'Forer le protocole sécurisé', + 'force_secure_desc' => 'Toujours rediriger l\'URL avec le schéma HTTPS.', + 'invalid_user' => 'Aucun utilisateur ne correspond aux identifiants fournis.', + 'invalid_activation_code' => 'Le code d’activation fourni est invalide.', + 'invalid_deactivation_pass' => 'Le mot de passe saisi est invalide.', + 'success_activation' => 'Votre compte a été activé avec succès !', + 'success_deactivation' => 'Votre compte a été désactivé avec succès. Nous somme navrés de vous voir partir !', + 'success_saved' => 'Vos paramètres ont été enregistrés avec succès !', + 'login_first' => 'Vous devez d’abord vous connecter !', + 'already_active' => 'Votre compte a déjà été activé !', + 'activation_email_sent' => 'Un e-mail d’activation a été envoyé sur votre adresse e-mail personnelle.', + 'registration_disabled' => 'La création de compte est désactivée pour le moment.', + 'sign_in' => 'Connexion', + 'register' => 'Créer un compte', + 'full_name' => 'Nom complet', + 'email' => 'E-mail', + 'password' => 'Mot de passe', + 'login' => 'Identifiant', + 'new_password' => 'Nouveau mot de passe', + 'new_password_confirm' => 'Confirmez le nouveau mot de passe', + ], + 'reset_password' => [ + 'reset_password' => 'Réinitialiser le mot de passe', + 'reset_password_desc' => 'Formulaire de récupération du mot de passe.', + 'code_param' => 'Code de réinitialisation', + 'code_param_desc' => 'URL de la page utilisée pour le code de réinitialisation', + ], + 'session' => [ + 'session' => 'Session', + 'session_desc' => 'Ajoute la session utilisateur à une page et permet de restreindre l’accès à la page.', + 'security_title' => 'Autorisations spéciales', + 'security_desc' => 'Personne(s) autorisée(s) à accéder à cette page.', + 'all' => 'Tous', + 'users' => 'Utilisateurs', + 'guests' => 'Invités', + 'allowed_groups_title' => 'Autoriser les groupes', + 'allowed_groups_description' => 'Choisissez les groupes autorisés ou aucun pour autoriser tous les groupes', + 'redirect_title' => 'Rediriger vers', + 'redirect_desc' => 'Nom de la page de redirection au cas où l’accès est refusé.', + 'logout' => 'Vous avez été déconnecté avec succès.', + 'stop_impersonate_success' => 'Vous n\'êtes plus en train d\'usurper l\'identité d\'un utilisateur', + ], + +]; diff --git a/plugins/rainlab/user/lang/hu/lang.php b/plugins/rainlab/user/lang/hu/lang.php new file mode 100644 index 0000000..ecc149f --- /dev/null +++ b/plugins/rainlab/user/lang/hu/lang.php @@ -0,0 +1,223 @@ + [ + 'name' => 'Felhasználók', + 'description' => 'Felhasználók menedzselése a weboldalon.', + 'tab' => 'Felhasználók', + 'access_users' => 'Fiókok kezelése', + 'access_groups' => 'Csoportok kezelése', + 'access_settings' => 'Beállítások kezelése', + 'impersonate_user' => 'Ãtjelentkezett felhasználók' + ], + 'users' => [ + 'menu_label' => 'Felhasználók', + 'all_users' => 'Felhasználók', + 'new_user' => 'Új felhasználó', + 'list_title' => 'Felhasználók kezelése', + 'trashed_hint_title' => 'A felhasználók felfüggeszthetik a saját fiókjukat', + 'trashed_hint_desc' => 'Amennyiben nem akarnak megjelenni a weboldalon, úgy deaktiválhatják a saját fiókjukat. Bármikor újra engedélyezhetik, ha újra sikeresen bejelentkeznek a weboldalra.', + 'banned_hint_title' => 'A felhasználó tiltva van', + 'banned_hint_desc' => 'Ezt a felhasználót már tiltotta egy adminisztrátor, így nem lesz képes bejelentkezni.', + 'guest_hint_title' => 'Vendég felhasználó', + 'guest_hint_desc' => 'Ez a felhasználó ideglenesen lett eltárolva. Regisztrálnia kell, mielÅ‘tt bejelentkezik a weboldalra.', + 'activate_warning_title' => 'Nincs aktiválva a felhasználó!', + 'activate_warning_desc' => 'Ennek a felhasználónak nem történt meg az aktiválása, így nem tud bejelentkezni.', + 'activate_confirm' => 'Valóban aktiválni akarja ezt a felhasználót?', + 'activated_success' => 'A felhasználó aktiválása megtörtént', + 'activate_manually' => 'A felhasználó kézi aktiválása', + 'convert_guest_confirm' => 'Legyen átkonvertálva teljes értékű felhasználóvá?', + 'convert_guest_manually' => 'Felhasználóvá konvertálás', + 'convert_guest_success' => 'A felhasználó konvertálása sikeresen megtörtént.', + 'impersonate_user' => 'Ãtjelentkezés a fiókba', + 'impersonate_confirm' => 'Biztos benne, hogy átjelentkezik a felhasználó saját fiókjába? Ezáltal a jelenlegi munkamenetbÅ‘l ki lesz jelentkeztetve.', + 'impersonate_success' => 'Sikeresen átjelentkezett a másik fiókba', + 'delete_confirm' => 'Valóban törölni akarja ezt a felhasználót?', + 'unban_user' => 'Felhasználó engedélyezése', + 'unban_confirm' => 'Valóban engedélyezni akarja ezt a felhasználót?', + 'unbanned_success' => 'A felhasználó sikeresen engedélyezve lett.', + 'return_to_list' => 'Vissza a felhasználó listához', + 'update_details' => 'Adatok módosítása', + 'bulk_actions' => 'Műveletek', + 'delete_selected' => 'Eltávolítás', + 'delete_selected_confirm' => 'Valóban törölni akarja a kiválasztott felhasználókat?', + 'delete_selected_empty' => 'Nincs kiválasztva felhasználó a törléshez.', + 'delete_selected_success' => 'A kiválasztott felhasználók sikeresen törölve lettek.', + 'activate_selected' => 'Aktiválás', + 'activate_selected_confirm' => 'Valóban aktiválni akarja a kiválasztott felhasználókat?', + 'activate_selected_empty' => 'Nincs kiválasztva felhasználó az aktiváláshoz.', + 'activate_selected_success' => 'A kiválasztott felhasználók sikeresen aktiválva lettek.', + 'deactivate_selected' => 'Deaktiválás', + 'deactivate_selected_confirm' => 'Valóban deaktiválni akarja a kiválasztott felhasználókat?', + 'deactivate_selected_empty' => 'Nincs kiválasztva felhasználó a deaktiváláshoz.', + 'deactivate_selected_success' => 'A kiválasztott felhasználók sikeresen deaktiválva lettek.', + 'restore_selected' => 'Visszaállítás', + 'restore_selected_confirm' => 'Valóban vissza akarja állítani a kiválasztott felhasználókat?', + 'restore_selected_empty' => 'Nincs kiválasztva felhasználó a visszaállításhoz.', + 'restore_selected_success' => 'A kiválasztott felhasználók sikeresen vissza lettek állítva.', + 'ban_selected' => 'Letiltás', + 'ban_selected_confirm' => 'Valóban tiltani akarja a kiválasztott felhasználókat?', + 'ban_selected_empty' => 'Nincs kiválasztva felhasználó a tiltáshoz.', + 'ban_selected_success' => 'A kiválasztott felhasználók sikeresen tiltva lettek.', + 'unban_selected' => 'Engedélyezés', + 'unban_selected_confirm' => 'Valóban engedélyezni akarja a kiválasztott felhasználókat?', + 'unban_selected_empty' => 'Nincs kiválasztva felhasználó az engedélyezéshez.', + 'unban_selected_success' => 'A kiválasztott felhasználók sikeresen engedélyezve lettek.', + 'unsuspend' => 'Felfüggesztés', + 'unsuspend_success' => 'A felfüggesztés sikeresen megtörtént.', + 'unsuspend_confirm' => 'Felfüggeszti a felhasználót?' + ], + 'settings' => [ + 'users' => 'Felhasználók', + 'menu_label' => 'Beállítások', + 'menu_description' => 'A felhasználókhoz tartozó beállítások kezelése.', + 'activation_tab' => 'Aktiválás', + 'signin_tab' => 'Bejelentkezés', + 'registration_tab' => 'Regisztráció', + 'profile_tab' => 'Profil', + 'notifications_tab' => 'Értesítések', + 'allow_registration' => 'Regisztráció engedélyezése', + 'allow_registration_comment' => 'Tiltás esetén csak az adminisztrátorok adhatnak hozzá felhasználót.', + 'activate_mode' => 'Aktiválási mód', + 'activate_mode_comment' => 'Válassza ki, hogyan kell aktiválni egy felhasználói fiókot.', + 'activate_mode_auto' => 'Automatikus', + 'activate_mode_auto_comment' => 'Regisztráláskor automatikusan aktiválva.', + 'activate_mode_user' => 'Felhasználó', + 'activate_mode_user_comment' => 'A felhasználó levéllel aktiválja a saját fiókját.', + 'activate_mode_admin' => 'Adminisztrátor', + 'activate_mode_admin_comment' => 'Csak adminisztrátor aktiválhat felhasználót.', + 'require_activation' => 'A bejelentkezéshez aktiválás szükséges', + 'require_activation_comment' => 'A felhasználóknak aktivált fiókkal kell rendelkezniük a bejelentkezéshez.', + 'use_throttle' => 'Kísérletek késleltetése', + 'use_throttle_comment' => 'Az ismétlÅ‘dÅ‘ sikertelen bejelentkezések ideiglenesen felfüggesztik a felhasználót.', + 'use_register_throttle' => 'Többszörös regisztráció', + 'use_register_throttle_comment' => 'Akadályozzon meg több regisztrációt ugyanarról az IP-rÅ‘l, ha röviddel egymás után történnek.', + 'block_persistence' => 'Egyidejű munkamenet', + 'block_persistence_comment' => 'Engedélyezés esetén a felhasználók nem tudnak bejelentkezni egyszerre több eszközrÅ‘l.', + 'login_attribute' => 'Bejelentkezési azonosító', + 'login_attribute_comment' => 'Válassza ki, hogy milyen felhasználói adatot kell használni a bejelentkezéshez.', + 'remember_login' => 'Emlékezzen a felhasználóra', + 'remember_login_comment' => 'Válassza ki az alábbiak közül a munkamenet idÅ‘tartalmát.', + 'remember_always' => 'Mindig', + 'remember_never' => 'Soha', + 'remember_ask' => 'Kérdezzen rá' + ], + 'user' => [ + 'label' => 'Felhasználó', + 'id' => 'Azonosító', + 'username' => 'Felhasználónév', + 'name' => 'Név', + 'name_empty' => 'Ismeretlen', + 'surname' => 'Családnév', + 'email' => 'E-mail cím', + 'created_at' => 'Regisztrált', + 'last_seen' => 'Belépve', + 'is_guest' => 'Vendég', + 'joined' => 'Csatlakozva', + 'is_online' => 'ElérhetÅ‘', + 'is_offline' => 'Nem elérhetÅ‘', + 'send_invite' => 'Üdvözlés küldése e-mailben', + 'send_invite_comment' => 'A kimenÅ‘ levél tartalmazza a felhasználónevet és jelszót.', + 'create_password' => 'Jelszó megadása', + 'create_password_comment' => 'Kérjük használjon egyedi és erÅ‘s jelszót.', + 'reset_password' => 'Új jelszó megadása', + 'reset_password_comment' => 'Kérjük használjon egyedi és erÅ‘s jelszót.', + 'confirm_password' => 'Jelszó megerÅ‘sítése', + 'confirm_password_comment' => 'Kérjük gépelje be újra a jelszót.', + 'groups' => 'Csoportok', + 'empty_groups' => 'Nincs létrehozva csoport.', + 'avatar' => 'Profilkép', + 'details' => 'Adatok', + 'account' => 'Fiók', + 'block_mail' => 'Az összes kimenÅ‘ levél tiltása ennél a felhasználónál.', + 'status_guest' => 'Vendég', + 'status_activated' => 'Aktivált', + 'status_registered' => 'Regisztrált', + 'created_ip_address' => 'Létrehozott IP cím', + 'last_ip_address' => 'Legutóbbi IP cím' + ], + 'group' => [ + 'label' => 'Csoport', + 'id' => 'Azonosító', + 'name' => 'Név', + 'description_field' => 'Leírás', + 'code' => 'Kód', + 'code_comment' => 'Egyedi azonosító az API eléréshez.', + 'created_at' => 'Létrehozva', + 'users_count' => 'Felhasználók' + ], + 'groups' => [ + 'menu_label' => 'Csoportok', + 'all_groups' => 'Csoportok', + 'new_group' => 'Új csoport', + 'delete_selected_confirm' => 'Valóban törölni akarja a kijelölt csoportokat?', + 'list_title' => 'Csoportok kezelése', + 'delete_confirm' => 'Valóban törölni akarja ezt a csoportot?', + 'delete_selected_success' => 'A csoportok sikeresen eltávolításra kerültek.', + 'delete_selected_empty' => 'A törléshez elÅ‘bb ki kell választania legalább egy csoportot.', + 'return_to_list' => 'Vissza a csoportokhoz', + 'return_to_users' => 'Vissza a felhasználókhoz', + 'create_title' => 'Csoport létrehozása', + 'update_title' => 'Csoport szerkesztése', + 'preview_title' => 'Csoport elÅ‘nézete' + ], + 'login' => [ + 'attribute_email' => 'E-mail cím', + 'attribute_username' => 'Felhasználónév' + ], + 'account' => [ + 'account' => 'Fiók', + 'account_desc' => 'Felhasználó kezelési űrlap.', + 'banned' => 'Sajnáljuk, ez a felhasználói fiók nincs aktiválva. Kérjük vegye fel a kapcsolatot a weboldal üzemeltetÅ‘jével.', + 'redirect_to' => 'Ãtirányítás', + 'redirect_to_desc' => 'Az oldal neve az átirányításhoz frissítés, bejelentkezés vagy regisztrálás után.', + 'code_param' => 'Aktiválási kód', + 'code_param_desc' => 'A regisztrálás aktiválási kódjához használt oldal webcíme.', + 'force_secure' => 'Biztonságos protokoll kényszerítése', + 'force_secure_desc' => 'A webcím mindig legyen átírányítva HTTPS protokollra.', + 'invalid_user' => 'Nem található a megadott hitelesítési adatokkal rendelkezÅ‘ felhasználó.', + 'invalid_activation_code' => 'A megadott aktiválási kód érvénytelen.', + 'invalid_deactivation_pass' => 'A megadott jelszó érvénytelen.', + 'invalid_current_pass' => 'A megadott jelenlegi jelszó érvénytelen.', + 'success_activation' => 'A fiók aktiválása sikerült.', + 'success_deactivation' => 'Sikeresen felfüggesztette a fiókját. További szép napot kívánunk!', + 'success_saved' => 'Sikerült menteni a beállításokat!', + 'login_first' => 'ElÅ‘bb be kell jelentkeznie!', + 'already_active' => 'Már aktiválta a fiókját!', + 'activation_email_sent' => 'Az aktiválási e-mail elküldése sikeresen megtörtént.', + 'activation_by_admin' => 'A regisztráció sikeresen megtörtént! A fiókja még nem aktív, azt a weboldal üzemeltetÅ‘jének még jóvá kell hagynia.', + 'registration_disabled' => 'A regisztráció jelenleg tiltva van az oldalon.', + 'registration_throttled' => 'Az újbóli regisztráció nem engedélyezett. Kérjük próbálja meg késÅ‘bb.', + 'sign_in' => 'Bejelentkezés', + 'register' => 'Regisztráció', + 'full_name' => 'Teljes név', + 'email' => 'E-mail cím', + 'password' => 'Jelszó', + 'login' => 'Bejelentkezés', + 'new_password' => 'Új jelszó', + 'new_password_confirm' => 'Új jelszó megerÅ‘sítése', + 'update_requires_password' => 'Biztonságos adatmódosítás', + 'update_requires_password_comment' => 'A profil megváltoztatásakor a rendszer elkéri a felhasználó jelenlegi jelszavát.' + ], + 'reset_password' => [ + 'reset_password' => 'Új jelszó megadása', + 'reset_password_desc' => 'Elfelejtett jelszó űrlap.', + 'code_param' => 'Visszaállító kód', + 'code_param_desc' => 'A visszaállító kódhoz használt oldal webcíme.' + ], + 'session' => [ + 'session' => 'Munkamenet', + 'session_desc' => 'Hozzáadja egy oldqalhoz a felhasználói munkamenetet és korlátozhatja az oldalhoz való hozzáférést.', + 'security_title' => 'Csak engedélyezés', + 'security_desc' => 'Ki számára engedélyezett a hozzáférés ehhez az oldalhoz.', + 'all' => 'Mindenki', + 'users' => 'Felhasználók', + 'guests' => 'Vendégek', + 'allowed_groups_title' => 'Csoportok engedélyezése', + 'allowed_groups_description' => 'Válassza ki az engedélyezni kívánt csoportokat vagy egyiket sem az összes elfogadásához.', + 'redirect_title' => 'Ãtirányítás', + 'redirect_desc' => 'Az átirányítandó oldal neve, ha a hozzáférés meg van tagadva.', + 'logout' => 'Sikeresen kijelentkezett!', + 'stop_impersonate_success' => 'Sikeresen visszajelentkezett az eredeti profiljába.' + ] +]; diff --git a/plugins/rainlab/user/lang/id/lang.php b/plugins/rainlab/user/lang/id/lang.php new file mode 100644 index 0000000..3b40083 --- /dev/null +++ b/plugins/rainlab/user/lang/id/lang.php @@ -0,0 +1,219 @@ + [ + 'name' => 'Pengguna', + 'description' => 'Manajemen pengguna front-end', + 'tab' => 'Pengguna', + 'access_users' => 'Kelola Pengguna', + 'access_groups' => 'Kelola Grup Pengguna', + 'access_settings' => 'Kelola Pengaturan Pengguna', + 'impersonate_user' => 'Menyamar Sebagai Pengguna' + ], + 'users' => [ + 'menu_label' => 'Pengguna', + 'all_users' => 'Semua Pengguna', + 'new_user' => 'Pengguna Baru', + 'list_title' => 'Kelola Pengguna', + 'trashed_hint_title' => 'Pengguna telah menonaktifkan akunnya', + 'trashed_hint_desc' => 'Pengguna ini telah menonaktifkan akunnya dan tidak ingin terlihat lagi di situs ini. Mereka dapat memulihkan akun mereka kapan saja dengan login kembali.', + 'banned_hint_title' => 'Pengguna telah diblokir', + 'banned_hint_desc' => 'Pengguna ini telah diblokir oleh administrator dan tidak dapat login.', + 'guest_hint_title' => 'Ini adalah pengguna tamu', + 'guest_hint_desc' => 'Pengguna ini disimpan untuk tujuan referensi saja dan perlu mendaftar sebelum login.', + 'activate_warning_title' => 'Pengguna tidak diaktifkan!', + 'activate_warning_desc' => 'Pengguna ini belum diaktifkan dan mungkin tidak dapat login.', + 'activate_confirm' => 'Apakah Anda benar-benar ingin mengaktifkan pengguna ini?', + 'activated_success' => 'Pengguna telah diaktifkan', + 'activate_manually' => 'Aktifkan pengguna ini secara manual', + 'convert_guest_confirm' => 'Ubah tamu menjadi penguna?', + 'convert_guest_manually' => 'Ubah tamu menjadi pengguna yang terdaftar', + 'convert_guest_success' => 'Pengguna telah diubah menjadi akun yang terdaftar', + 'impersonate_user' => 'Menyamar sebagai pengguna', + 'impersonate_confirm' => 'Menyamar sebagai pengguna? Anda dapat kembali ke keadaan semula dengan logout.', + 'impersonate_success' => 'Anda sekarang menyamar sebagai pengguna ini', + 'delete_confirm' => 'Apakah Anda benar-benar ingin menghapus pengguna ini?', + 'unban_user' => 'Batalkan pemblokiran pengguna ini', + 'unban_confirm' => 'Apakah Anda benar-benar ingin membatalkan pemblokiran pengguna ini?', + 'unbanned_success' => 'Pengguna tidak lagi diblokir', + 'return_to_list' => 'Kembali ke list pengguna', + 'update_details' => 'Perbarui detail', + 'bulk_actions' => 'Aksi masal', + 'delete_selected' => 'Hapus yang dipilih', + 'delete_selected_confirm' => 'Hapus pengguna yang dipilih?', + 'delete_selected_empty' => 'Tidak ada pengguna yang dipilih untuk dihapus.', + 'delete_selected_success' => 'Berhasil menghapus pengguna yang dipilih.', + 'activate_selected' => 'Aktifkan yang dipilih', + 'activate_selected_confirm' => 'Aktifkan pengguna yang dipilih?', + 'activate_selected_empty' => 'Tidak ada pengguna yang dipilih untuk diaktifkan.', + 'activate_selected_success' => 'Berhasil mengaktifkan pengguna yang dipilih.', + 'deactivate_selected' => 'Nonaktifkan yang dipilih', + 'deactivate_selected_confirm' => 'Nonaktifkan pengguna yang dipilih?', + 'deactivate_selected_empty' => 'Tidak ada pengguna yang dipilih untuk dinonaktifkan.', + 'deactivate_selected_success' => 'Berhasil menonaktifkan pengguna yang dipilih.', + 'restore_selected' => 'Pulihkan yang dipilih', + 'restore_selected_confirm' => 'Pulihkan pengguna yang dipilih?', + 'restore_selected_empty' => 'Tidak ada pengguna yang dipilih untuk dipulihkan.', + 'restore_selected_success' => 'Berhasil memulihkan pengguna yang dipilih.', + 'ban_selected' => 'Blokir yang dipilih', + 'ban_selected_confirm' => 'Blokir pengguna yang dipilih?', + 'ban_selected_empty' => 'Tidak ada pengguna yang dipilih untuk diblokir.', + 'ban_selected_success' => 'Berhasil memblokir pengguna yang dipilih.', + 'unban_selected' => 'Batalkan pemblokiran yang dipilih', + 'unban_selected_confirm' => 'Batalkan pemblokiran pengguna yang dipilih?', + 'unban_selected_empty' => 'Tidak ada pengguna yang dipilih untuk dibatalkan pemblokirannya.', + 'unban_selected_success' => 'Berhasil membatalkan pemblokiran pengguna yang dipilih.', + ], + 'settings' => [ + 'users' => 'Pengguna', + 'menu_label' => 'Pengaturan pengguna', + 'menu_description' => 'Kelola pengaturan berbasis pengguna', + 'activation_tab' => 'Aktivasi', + 'signin_tab' => 'Login', + 'registration_tab' => 'Pendaftaran', + 'profile_tab' => 'Profil', + 'notifications_tab' => 'Notifikasi', + 'allow_registration' => 'Izinkan pendaftaran', + 'allow_registration_comment' => 'Jika tidak diaktfkan, pengguna hanya bisa dibuat oleh administrator.', + 'activate_mode' => 'Mode aktivasi', + 'activate_mode_comment' => 'Tentukan bagaimana akun pengguna haris diaktifkan', + 'activate_mode_auto' => 'Otomatis', + 'activate_mode_auto_comment' => 'Diaktifkan secara otomatis setelah pendaftaran.', + 'activate_mode_user' => 'Pengguna', + 'activate_mode_user_comment' => 'Pengguna mengaktifkan akun mereka menggunakan email.', + 'activate_mode_admin' => 'Administrator', + 'activate_mode_admin_comment' => 'Hanya administrator yang bisa mengaktifkan pengguna.', + 'require_activation' => 'Login memerlukan aktivasi', + 'require_activation_comment' => 'Pengguna harus aktif sebelum bisa login.', + 'use_throttle' => 'Upaya penangguhan', + 'use_throttle_comment' => 'Mengulangi upaya login yang gagal akan menangguhkan pengguna untuk sementara.', + 'use_register_throttle' => 'Pencekalan pendaftaran', + 'use_register_throttle_comment' => 'Cegah pendaftaran dari IP yang sama dalam kurun waktu singkat.', + 'block_persistence' => 'Cegah sesi bersamaan', + 'block_persistence_comment' => 'Saat diaktifkan, pengguna tidak dapat login ke beberapa perangkat secara bersamaan.', + 'login_attribute' => 'Atribut login', + 'login_attribute_comment' => 'Pilih detail atribut apa yang harus digunakan untuk masuk.', + 'remember_login' => 'Mode ingat login', + 'remember_login_comment' => 'Tentukan jika sesi pengguna harus persisten.', + 'remember_always' => 'Selalu', + 'remember_never' => 'Jangan pernah', + 'remember_ask' => 'Tanyakan saat login', + ], + 'user' => [ + 'label' => 'Pengguna', + 'id' => 'ID', + 'username' => 'Nama pengguna', + 'name' => 'Nama', + 'name_empty' => 'Anonim', + 'surname' => 'Nama keluarga', + 'email' => 'Email', + 'created_at' => 'Terdaftar', + 'last_seen' => 'Terakhir dilihat', + 'is_guest' => 'Tamu', + 'joined' => 'Bergabung', + 'is_online' => 'Sedang online', + 'is_offline' => 'Sedang offline', + 'send_invite' => 'Kirim undangan via email', + 'send_invite_comment' => 'Kirim pesan selamat datang dengan menyertakan informasi login dan kata sandi.', + 'create_password' => 'Buat Sandi', + 'create_password_comment' => 'Buat kata sandi baru untuk masuk.', + 'reset_password' => 'Setel Ulang Kata Sandi', + 'reset_password_comment' => 'Untuk menyetel ulang sandi, masukkan kata sandi baru disini.', + 'confirm_password' => 'Konfirmasi Kata Sandi', + 'confirm_password_comment' => 'Masukkan kembali kata sandi untuk konfirmasi.', + 'groups' => 'Grup', + 'empty_groups' => 'Tidak ada grup pengguna yang tersedia.', + 'avatar' => 'Avatar', + 'details' => 'Detail', + 'account' => 'Akun', + 'block_mail' => 'Blokir semua pesan keluar yang dikirim ke pengguna ini.', + 'status_guest' => 'Tamu', + 'status_activated' => 'Diaktifkan', + 'status_registered' => 'Terdaftar', + 'created_ip_address' => 'Alamat IP Telah Dibuat', + 'last_ip_address' => 'Alamat IP Terakhir', + ], + 'group' => [ + 'label' => 'Grup', + 'id' => 'ID', + 'name' => 'Nama', + 'description_field' => 'Deskripsi', + 'code' => 'Kode', + 'code_comment' => 'Masukkan kode unik untuk mengidentifikasi grup ini.', + 'created_at' => 'Dibuat', + 'users_count' => 'Pengguna' + ], + 'groups' => [ + 'menu_label' => 'Grup', + 'all_groups' => 'Grup Pengguna', + 'new_group' => 'Grup Baru', + 'delete_selected_confirm' => 'Apakah Anda benar-benar ingin menghapus grup yang dipilih?', + 'list_title' => 'Kelola Grup', + 'delete_confirm' => 'Apakah Anda benar-benar ingin menghapus grup ini?', + 'delete_selected_success' => 'Berhasil menghapus grup yang dipilih.', + 'delete_selected_empty' => 'Tidak ada grup yang dipilih untuk dihapus.', + 'return_to_list' => 'Kembali ke daftar grup', + 'return_to_users' => 'Kembali ke daftar pengguna', + 'create_title' => 'Buat Grup Pengguna', + 'update_title' => 'Edit Grup Pengguna', + 'preview_title' => 'Pratinjau Grup Pengguna' + ], + 'login' => [ + 'attribute_email' => 'Email', + 'attribute_username' => 'Nama Pengguna' + ], + 'account' => [ + 'account' => 'Akun', + 'account_desc' => 'Formulir manajemen pengguna.', + 'banned' => 'Maaf, pengguna saat ini tidak diaktifkan. Silakan hubungi kami untuk bantuan lebih lanjut.', + 'redirect_to' => 'Alihkan ke', + 'redirect_to_desc' => 'Nama halaman untuk dialihkan setelah pembaruan, masuk atau registrasi.', + 'code_param' => 'Parameter Kode Aktivasi', + 'code_param_desc' => 'Parameter URL pada halaman yang digunakan untuk kode aktivasi pendaftaran', + 'force_secure' => 'Paksa protokol yang aman', + 'force_secure_desc' => 'Selalu mengarahkan URL dengan skema HTTPS.', + 'invalid_user' => 'Pengguna dengan kredensial yang diberikan tidak ditemukan.', + 'invalid_activation_code' => 'Kode aktivasi yang diberikan tidak valid.', + 'invalid_deactivation_pass' => 'Kata sandi yang diberikan tidak valid.', + 'invalid_current_pass' => 'Kata sandi saat ini yang Anda masukkan tidak valid.', + 'success_activation' => 'Berhasil mengaktifkan akun Anda.', + 'success_deactivation' => 'Berhasil menonaktifkan akun Anda. Sedih melihat Anda pergi!', + 'success_saved' => 'Pengaturan berhasil disimpan!', + 'login_first' => 'Anda harus masuk terlebih dahulu!', + 'already_active' => 'Akun Anda sudah diaktifkan!', + 'activation_email_sent' => 'Email aktivasi telah dikirim ke alamat email Anda.', + 'registration_disabled' => 'Pendaftaran saat ini dinonaktifkan.', + 'registration_throttled' => 'Registrasi dibatasi. Silakan coba lagi nanti.', + 'sign_in' => 'Masuk', + 'register' => 'Daftar', + 'full_name' => 'Nama Lengkap', + 'email' => 'Email', + 'password' => 'Kata Sandi', + 'login' => 'Login', + 'new_password' => 'Kata Sandi Baru', + 'new_password_confirm' => 'Konfirmasi Kata Sandi Baru', + 'update_requires_password' => 'Konfirmasikan kata sandi saat pembaruan', + 'update_requires_password_comment' => 'Kata sandi diperlukan saat mengubah profil.' + ], + 'reset_password' => [ + 'reset_password' => 'Setel Ulang Kata Sandi', + 'reset_password_desc' => 'Formulir lupa kata sandi.', + 'code_param' => 'Parameter Penyetelan Ulang Kata Sandi', + 'code_param_desc' => 'Parameter URL pada halaman yang digunakan untuk kode reset' + ], + 'session' => [ + 'session' => 'Sesi', + 'session_desc' => 'Menambahkan sesi pengguna ke halaman dan dapat membatasi akses halaman.', + 'security_title' => 'Hanya izinkan', + 'security_desc' => 'Siapa yang diizinkan mengakses halaman.', + 'all' => 'Semua', + 'users' => 'Pengguna', + 'guests' => 'Tamu', + 'allowed_groups_title' => 'Izinkan grup', + 'allowed_groups_description' => 'Pilih grup yang diizinkan, atau pilih tidak ada untuk mengizinkan semua grup', + 'redirect_title' => 'Alihkan ke', + 'redirect_desc' => 'Nama halaman untuk dialihkan jika akses ditolak.', + 'logout' => 'Anda telah berhasil keluar!', + 'stop_impersonate_success' => 'Anda tidak lagi bertidak sebagai pengguna.', + ] +]; diff --git a/plugins/rainlab/user/lang/it/lang.php b/plugins/rainlab/user/lang/it/lang.php new file mode 100644 index 0000000..2bb08f8 --- /dev/null +++ b/plugins/rainlab/user/lang/it/lang.php @@ -0,0 +1,192 @@ + [ + 'name' => 'Utenti', + 'description' => 'Gestione Utenti Front-End.', + 'tab' => 'Utenti', + 'access_users' => 'Gestisci Utenti', + 'access_groups' => 'Gestisci Gruppi di Utenti', + 'access_settings' => 'Gestisci Impostazioni Utenti' + ], + 'users' => [ + 'menu_label' => 'Utenti', + 'all_users' => 'Tutti gli utenti', + 'new_user' => 'Nuovo Utente', + 'list_title' => 'Gestisci Utenti', + 'trashed_hint_title' => 'L\'utente ha disabilitato il suo account', + 'trashed_hint_desc' => 'Questo utente ha disattivato il suo account and e non vuole più apparire sul sito. Possono riattivarsi in qualsiasi momento effettuando l\'accesso.', + 'banned_hint_title' => 'Questo utente è stato bannato', + 'banned_hint_desc' => 'Questo utente è stato bannato da un amministratore e non potrà piú effettuare l\'accesso', + 'guest_hint_title' => 'Questo è un utente anonimo', + 'guest_hint_desc' => 'Questo utente è salvato solo per riferimento e deve registrarsi prima di poter effettuare l\'accesso', + 'activate_warning_title' => 'Utente non attivo!', + 'activate_warning_desc' => 'Questo utente non è stato attivato e potrebbe non essere in grado di effettuare l\'accesso', + 'activate_confirm' => 'Vuoi veramente attivare questo utente?', + 'activated_success' => 'Utente Attivato', + 'activate_manually' => 'Attiva questo utente manualmente', + 'convert_guest_confirm' => 'Convertire questo utente anonimo a un utente registrato?', + 'convert_guest_manually' => 'Converti a un utente registrato', + 'convert_guest_success' => 'Utente convertito a un account registrato', + 'delete_confirm' => 'Vuoi veramente cancellare questo utente?', + 'unban_user' => 'Sblocca questo utente', + 'unban_confirm' => 'Vuoi veramente sbloccare questo utente?', + 'unbanned_success' => 'L\'utente è stato sbloccato', + 'return_to_list' => 'Ritorna alla lista utenti', + 'update_details' => 'Aggiorna dettagli', + 'bulk_actions' => 'Azioni multiple', + 'delete_selected' => 'Elimina selezionati', + 'delete_selected_confirm' => 'Eliminare gli utenti selezionati?', + 'delete_selected_empty' => 'Non ci sono utenti selezionati da cancellare.', + 'delete_selected_success' => 'Gli utenti selezionati sono stati cancellati con successo.', + 'deactivate_selected' => 'Disabilita selezionati', + 'deactivate_selected_confirm' => 'Disattivare gli utenti selezionati?', + 'deactivate_selected_empty' => 'Non ci sono utenti selezionati da disattivare.', + 'deactivate_selected_success' => 'Utenti selezionati disattivati con successo.', + 'restore_selected' => 'Ripristina selezionati', + 'restore_selected_confirm' => 'Ripristinare gli utenti selezionati?', + 'restore_selected_empty' => 'Non ci sono utenti selezionati da ripristinare.', + 'restore_selected_success' => 'Utenti selezionati ripristinati con successo.', + 'ban_selected' => 'Blocca selezionati', + 'ban_selected_confirm' => 'Bloccare l\'utente selezionato?', + 'ban_selected_empty' => 'Non ci sono utenti selezionati da bloccare.', + 'ban_selected_success' => 'Utenti selezionati bloccati con successo.', + 'unban_selected' => 'Sblocca selezionati', + 'unban_selected_confirm' => 'Sbloccare gli utenti selezionati?', + 'unban_selected_empty' => 'Non ci sono utenti selezionati da sbloccare.', + 'unban_selected_success' => 'Utenti selezionati sbloccati con successo.', + ], + 'settings' => [ + 'users' => 'Utenti', + 'menu_label' => 'Impostazioni Utenti', + 'menu_description' => 'Gestisci impostazioni degli utenti', + 'activation_tab' => 'Attivazione', + 'signin_tab' => 'Accesso', + 'registration_tab' => 'Registrazione', + 'notifications_tab' => 'Notifiche', + 'allow_registration' => 'Consenti registrazione utenti', + 'allow_registration_comment' => 'Se questo è disabilitato gli utenti possono essere creati solo da un amministratore.', + 'activate_mode' => 'Modalità di attivazione', + 'activate_mode_comment' => 'Scegli come un utente dovrebbe essere attivato', + 'activate_mode_auto' => 'Automaticamente', + 'activate_mode_auto_comment' => 'Attivato automaticamente alla registrazione', + 'activate_mode_user' => 'Utente', + 'activate_mode_user_comment' => 'L\'utente si attiva da solo confermando la sua email', + 'activate_mode_admin' => 'Amministratore', + 'activate_mode_admin_comment' => 'Solo un amminstratore può attivare un utente.', + 'require_activation' => 'Effettuare l\'accesso richiede l\'attivazione.', + 'require_activation_comment' => 'Gli utenti devono avere un account attivato per effettuare l\'accesso.', + 'block_persistence' => 'Previeni sessioni concorrenti', + 'block_persistence_comment' => 'Quando abilitato gli utenti non possono effettuare il log-in da diversi dispositivi contemporaneamente', + 'use_throttle' => 'Limita tentativi', + 'use_throttle_comment' => 'Ripetuti tentativi errati di accesso porteranno alla sospensione temporanea dell\'utente.', + 'login_attribute' => 'Metodo di login', + 'login_attribute_comment' => 'Seleziona che attributo gli utenti useranno per effettuare il login.' , + ], + 'user' => [ + 'label' => 'Utente', + 'id' => 'ID', + 'username' => 'Username', + 'name' => 'Nome', + 'name_empty' => 'Anonimo', + 'surname' => 'Cognome', + 'email' => 'Email', + 'created_at' => 'Registrato', + 'last_seen' => 'Ultimo accesso', + 'is_guest' => 'Anonimo', + 'joined' => 'Joined', + 'is_online' => 'Online adesso', + 'is_offline' => 'Al momento non collegato', + 'send_invite' => 'Invia invito via mail', + 'send_invite_comment' => 'Invia un messaggio di benvenuto contenente le informazioni per l\'accesso', + 'create_password' => 'Crea Password', + 'create_password_comment' => 'Inserisci una nuova password per l\'accesso.', + 'reset_password' => 'Cambia la Password', + 'reset_password_comment' => 'Per cambiare la password di questo utente, inserisci una nuova password quí', + 'confirm_password' => 'Conferma Password', + 'confirm_password_comment' => 'Inserisci nuovamente la password per confermare.', + 'groups' => 'Gruppi', + 'empty_groups' => 'Non ci sono gruppi di utenti disponibili.', + 'avatar' => 'Avatar', + 'details' => 'Dettagli', + 'account' => 'Account', + 'block_mail' => 'Blocca tutte le mail verso questo utente.', + 'status_guest' => 'Anonimo', + 'status_activated' => 'Attivato', + 'status_registered' => 'Registrato', + ], + 'group' => [ + 'label' => 'Gruppo', + 'id' => 'ID', + 'name' => 'Nome', + 'description_field' => 'Descrizione', + 'code' => 'Codice', + 'code_comment' => 'Inserisci un codice univoco per identificare il gruppo.', + 'created_at' => 'Creato', + 'users_count' => 'Utenti' + ], + 'groups' => [ + 'menu_label' => 'Gruppi', + 'all_groups' => 'Gruppi di Utenti', + 'new_group' => 'Nuovo gruppo', + 'delete_selected_confirm' => 'Vuoi veramente cancellare i gruppi selezionati?', + 'list_title' => 'Gestisci Gruppi', + 'delete_confirm' => 'Vuoi veramente cancellare questo gruppo?', + 'delete_selected_success' => 'Gruppi selezionati cancellati con successo.', + 'delete_selected_empty' => 'Non ci sono gruppi selezionati da cancellare.', + 'return_to_list' => 'Torna all\'elenco dei gruppi', + 'return_to_users' => 'Torna alla lista utenti', + 'create_title' => 'Crea Gruppo di Utenti', + 'update_title' => 'Modifica Gruppo di Utenti', + 'preview_title' => 'Anteprima Gruppo' + ], + 'login' => [ + 'attribute_email' => 'Email', + 'attribute_username' => 'Username' + ], + 'account' => [ + 'account' => 'Account', + 'account_desc' => 'Form di gestione account.', + 'redirect_to' => 'Reindirizza A', + 'redirect_to_desc' => 'Pagina verso cui essere reindirizzati dopo modifica, accesso o registrazione.', + 'code_param' => 'Parametro codice di attivazione', + 'code_param_desc' => 'Parametro dell\'URL usato per il codice di attivazione', + 'invalid_user' => 'Impossibile effettuare il login con le credenziali fornite.', + 'invalid_activation_code' => 'Codice di attivazione fornito non valido.', + 'invalid_deactivation_pass' => 'La password inserita non è valida.', + 'success_activation' => 'Account attivato con successo.', + 'success_deactivation' => 'Account disattivato con successo. Ci dispiace vederti andare via!', + 'success_saved' => 'Impostazioni salvate con successo!', + 'login_first' => 'Devi prima effettuare l\'accesso!', + 'already_active' => 'Il tuo account è già stato attivato!', + 'activation_email_sent' => 'Una mail di attivazione è stata inviata al tuo indirizzo mail.', + 'activation_by_admin' => 'Registrazione effettuata con successo. Il tuo account non è ancora attivo e deve essere approvato da un amministratore.', + 'registration_disabled' => 'La registrazione è al momento disattivata.', + 'sign_in' => 'Accedi', + 'register' => 'Registra', + 'full_name' => 'Nome Completo', + 'email' => 'Email', + 'password' => 'Password', + 'login' => 'Login', + 'new_password' => 'Nuova Password', + 'new_password_confirm' => 'Conferma Nuova Password' + ], + 'reset_password' => [ + 'reset_password' => 'Ripristina Password', + 'reset_password_desc' => 'Form password dimenticata.', + 'code_param' => 'Parametro codice di ripristino', + 'code_param_desc' => 'Parametro dell\'URL usato per il codice di ripristino' + ], + 'session' => [ + 'session' => 'Sessione', + 'session_desc' => 'Aggiungi la sessione utente a una pagina per limitare l\'accesso.', + 'security_title' => 'Autorizza solo', + 'security_desc' => 'Chi è autorizzato ad accedere alla pagina.', + 'all' => 'Tutti', + 'users' => 'Utenti', + 'guests' => 'Anonimi', + 'redirect_title' => 'Reindirizza a', + 'redirect_desc' => 'Nome della pagina a cui reindirizzare se l\'accesso è negato.', + 'logout' => 'Sei stato scollegato con successo!' + ] +]; diff --git a/plugins/rainlab/user/lang/kr/lang.php b/plugins/rainlab/user/lang/kr/lang.php new file mode 100644 index 0000000..03badd4 --- /dev/null +++ b/plugins/rainlab/user/lang/kr/lang.php @@ -0,0 +1,205 @@ + [ + 'name' => '계정', + 'description' => '프론트 엔드 회ì›ê´€ë¦¬', + 'tab' => '회ì›ê´€ë¦¬', + 'access_users' => '회ì›ê´€ë¦¬', + 'access_groups' => '그룹관리', + 'access_settings' => '회ì›ì„¤ì •', + 'impersonate_user' => '위장 로그ì¸' + ], + 'users' => [ + 'menu_label' => '계정', + 'all_users' => '전체계정', + 'new_user' => '신규계정', + 'list_title' => '계정관리', + 'trashed_hint_title' => '사용ìžê°€ ê³„ì •ì„ ë¹„í™œì„±í™”í–ˆìŠµë‹ˆë‹¤.', + 'trashed_hint_desc' => 'ì´ ì‚¬ìš©ìžëŠ” ìžì‹ ì˜ ê³„ì •ì„ ë¹„í™œì„±í™”í–ˆìœ¼ë©° ë” ì´ìƒ 사ì´íŠ¸ì— ë‚˜íƒ€ë‚˜ê¸¸ ì›ì¹˜ 않습니다. 다시 로그ì¸í•˜ë©´ 언제든지 ê³„ì •ì„ ë³µì› í•  수 있습니다.', + 'banned_hint_title' => 'ì°¨ë‹¨ëœ ê³„ì •ìž…ë‹ˆë‹¤.', + 'banned_hint_desc' => 'ì´ ì‚¬ìš©ìžëŠ” 관리ìžì— ì˜í•´ 차단ë˜ì—ˆìœ¼ë©° ë¡œê·¸ì¸ í•  수 없습니다.', + 'guest_hint_title' => 'ë°©ë¬¸ìž ìž…ë‹ˆë‹¤.', + 'guest_hint_desc' => 'ì´ ê³„ì •ì€ ì°¸ì¡° 목ì ìœ¼ë¡œ ë§Œ 저장ë˜ë©° 로그ì¸í•˜ê¸° ì „ì— ë“±ë¡í•´ì•¼í•©ë‹ˆë‹¤.', + 'activate_warning_title' => '사용ìžê°€ 활성화ë˜ì§€ 않았습니다!', + 'activate_warning_desc' => 'ì´ ì‚¬ìš©ìžëŠ” 비활성화 ìƒíƒœì´ë©°, ë¡œê·¸ì¸ í•  수 없습니다.', + 'activate_confirm' => 'ì´ ì‚¬ìš©ìžë¥¼ 활성화하시겠습니까?', + 'activated_success' => '사용ìžê°€ 활성화ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'activate_manually' => '수ë™ìœ¼ë¡œ ì´ ì‚¬ìš©ìž í™œì„±í™”', + 'convert_guest_confirm' => 'ì´ ë°©ë¬¸ìžë¥¼ 계정으로 변환하시겠습니까?', + 'convert_guest_manually' => '등ë¡ëœ 사용ìžë¡œ 변환', + 'convert_guest_success' => '사용ìžê°€ 등ë¡ëœ 계정으로 변환ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'impersonate_user' => '가장 로그ì¸', + 'impersonate_confirm' => 'ì´ ì‚¬ìš©ìžë¡œ 가장하시겠습니까? 로그 아웃하면 ì›ëž˜ ìƒíƒœë¡œ ë˜ëŒë¦´ 수 있습니다.', + 'impersonate_success' => 'ì´ì œ ì´ ì‚¬ìš©ìžë¥¼ 가장하고 있습니다.', + 'delete_confirm' => 'ì´ ì‚¬ìš©ìžë¥¼ 삭제하시겠습니까??', + 'unban_user' => 'ì´ ì‚¬ìš©ìžì˜ ì°¨ë‹¨ì„ í•´ì œí•©ë‹ˆë‹¤.', + 'unban_confirm' => 'ì´ ì‚¬ìš©ìžì˜ ì°¨ë‹¨ì„ í•´ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?', + 'unbanned_success' => '사용ìžì˜ ì°¨ë‹¨ì´ í•´ì œë˜ì—ˆìŠµë‹ˆë‹¤.', + 'return_to_list' => 'ì‚¬ìš©ìž ëª©ë¡ìœ¼ë¡œ ëŒì•„가기', + 'update_details' => '세부 ì •ë³´ 수정', + 'bulk_actions' => '대량 작업', + 'delete_selected' => 'ì„ íƒ í•­ëª© ì‚­ì œ', + 'delete_selected_confirm' => 'ì„ íƒí•œ 사용ìžë¥¼ 삭제하시겠습니까?', + 'delete_selected_empty' => '삭제할 대ìƒì´ 없습니다.', + 'delete_selected_success' => 'ì„ íƒí•œ 사용ìžë¥¼ 성공ì ìœ¼ë¡œ 삭제했습니다.', + 'activate_selected' => 'ì„ íƒí•œ 항목 활성화', + 'activate_selected_confirm' => 'ì„ íƒí•œ 사용ìžë¥¼ 활성화하시겠습니까?', + 'activate_selected_empty' => '활성화할 ì„ íƒí•œ 사용ìžê°€ 없습니다.', + 'activate_selected_success' => 'ì„ íƒí•œ 사용ìžê°€ 성공ì ìœ¼ë¡œ 활성화ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'deactivate_selected' => '비활성화 ì„ íƒë¨', + 'deactivate_selected_confirm' => 'ì„ íƒí•œ 사용ìžë¥¼ 비활성화하시겠습니까?', + 'deactivate_selected_empty' => '비활성화할 ì„ íƒí•œ 사용ìžê°€ 없습니다.', + 'deactivate_selected_success' => 'ì„ íƒí•œ 사용ìžë¥¼ 성공ì ìœ¼ë¡œ 비활성화했습니다.', + 'restore_selected' => 'ë³µì› ì„ íƒë¨', + 'restore_selected_confirm' => 'ì„ íƒí•œ 사용ìžë¥¼ ë³µì›í•˜ì‹œê² ìŠµë‹ˆê¹Œ?', + 'restore_selected_empty' => 'ë³µì›í•  ì„ íƒí•œ 사용ìžê°€ 없습니다.', + 'restore_selected_success' => 'ì„ íƒí•œ 사용ìžë¥¼ 성공ì ìœ¼ë¡œ ë³µì›í–ˆìŠµë‹ˆë‹¤.', + 'ban_selected' => '차단 ì„ íƒ', + 'ban_selected_confirm' => 'ì„ íƒí•œ 사용ìžì˜ 차단하시겠습니까?', + 'ban_selected_empty' => '차단할 ì„ íƒëœ 사용ìžê°€ 없습니다.', + 'ban_selected_success' => 'ì„ íƒí•œ 사용ìžë¥¼ 성공ì ìœ¼ë¡œ 차단했습니다.', + 'unban_selected' => '차단해제 ì„ íƒ', + 'unban_selected_confirm' => 'ì„ íƒí•œ 사용ìžë¥¼ 차단해제하시겠습니까?', + 'unban_selected_empty' => '차단해제할 ì„ íƒí•œ 사용ìžê°€ 없습니다.', + 'unban_selected_success' => 'ì„ íƒí•œ 사용ìžë¥¼ 성공ì ìœ¼ë¡œ 차단해제했습니다.', + ], + 'settings' => [ + 'users' => '사용ìž', + 'menu_label' => 'ì‚¬ìš©ìž ì„¤ì •', + 'menu_description' => 'ì‚¬ìš©ìž ê¸°ë³¸ ì„¤ì •ì„ ê´€ë¦¬í•©ë‹ˆë‹¤.', + 'activation_tab' => '활성화', + 'signin_tab' => '로그ì¸', + 'registration_tab' => '등ë¡.', + 'notifications_tab' => '알림', + 'allow_registration' => 'ì‚¬ìš©ìž ë“±ë¡ í—ˆìš©', + 'allow_registration_comment' => 'ì´ ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ì§€ 않ë„ë¡ ì„¤ì •í•˜ë©´ 관리ìžë§Œ 사용ìžë¥¼ ìƒì„±í•  수 있습니다.', + 'activate_mode' => '활성화 모드', + 'activate_mode_comment' => 'ì‚¬ìš©ìž ê³„ì •ì„ í™œì„±í™”í•  ë°©ë²•ì„ ì„ íƒí•©ë‹ˆë‹¤.', + 'activate_mode_auto' => 'ìžë™', + 'activate_mode_auto_comment' => 'ë“±ë¡ ì‹œ ìžë™ìœ¼ë¡œ 활성화ë©ë‹ˆë‹¤.', + 'activate_mode_user' => '사용ìž', + 'activate_mode_user_comment' => '사용ìžê°€ ë©”ì¼ì„ 사용하여 ìžì‹ ì˜ ê³„ì •ì„ í™œì„±í™”í•©ë‹ˆë‹¤.', + 'activate_mode_admin' => '관리ìž', + 'activate_mode_admin_comment' => '관리ìžë§Œ 사용ìžë¥¼ 활성화할 수 있습니다.', + 'require_activation' => '로그ì¸ì„ 위해서는 활성화가 필요합니다.', + 'require_activation_comment' => '사용ìžê°€ 로그ì¸í•˜ë ¤ë©´ í™œì„±í™”ëœ ê³„ì •ì´ì—¬ì•¼ 합니다.', + 'use_throttle' => '스로틀 시ë„', + 'use_throttle_comment' => '실패한 ë¡œê·¸ì¸ ì‹œë„를 반복하면 사용ìžê°€ ì¼ì‹œì ìœ¼ë¡œ ì¼ì‹œ 중지ë©ë‹ˆë‹¤.', + 'block_persistence' => 'ë™ì‹œ 세션 ë°©ì§€', + 'block_persistence_comment' => 'í™œì„±í™”ëœ ê²½ìš° 사용ìžëŠ” í•œë²ˆì— ì—¬ëŸ¬ ìž¥ì¹˜ì— ë¡œê·¸ì¸í•  수 없습니다.', + 'login_attribute' => 'ë¡œê·¸ì¸ ì†ì„±', + 'login_attribute_comment' => '로그ì¸ì— 사용할 기본 ì‚¬ìš©ìž ì„¸ë¶€ 정보를 ì„ íƒí•©ë‹ˆë‹¤.', + ], + 'user' => [ + 'label' => '사용ìž', + 'id' => 'ì•„ì´ë””', + 'username' => 'ì‚¬ìš©ìž ì´ë¦„', + 'name' => 'ì´ë¦„', + 'name_empty' => 'ìµëª…', + 'surname' => '성', + 'email' => 'ì´ë©”ì¼', + 'created_at' => '등ë¡ì¼', + 'last_seen' => '마지막 활ë™', + 'is_guest' => 'ì†ë‹˜', + 'joined' => '가입ëœ', + 'is_online' => '지금 온ë¼ì¸', + 'is_offline' => '현재 오프ë¼ì¸ ìƒíƒœ', + 'send_invite' => 'ì´ë©”ì¼ë¡œ 초대 ë©”ì¼ ë³´ë‚´ê¸°', + 'send_invite_comment' => 'ë¡œê·¸ì¸ ë° ë¹„ë°€ë²ˆí˜¸ ì •ë³´ê°€ í¬í•¨ëœ í™˜ì˜ ë©”ì‹œì§€ë¥¼ 보냅니다.', + 'create_password' => '비밀번호 ìƒì„±', + 'create_password_comment' => '로그ì¸ì— 사용ë˜ëŠ” 새 비밀번호를 입력합니다.', + 'reset_password' => '비밀번호 재설정', + 'reset_password_comment' => 'ì´ ì‚¬ìš©ìž ì•”í˜¸ë¥¼ 재설정하려면 ì—¬ê¸°ì— ìƒˆ 암호를 입력하십시오.', + 'confirm_password' => '비밀번호 확ì¸', + 'confirm_password_comment' => '비밀번호를 다시 입력하여 확ì¸í•©ë‹ˆë‹¤.', + 'groups' => '그룹', + 'empty_groups' => '사용 가능한 ì‚¬ìš©ìž ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤.', + 'avatar' => '아바타', + 'details' => '세부 사항', + 'account' => '계정', + 'block_mail' => 'ì´ ì‚¬ìš©ìžì—게 보내는 보내는 ë©”ì¼ì„ ëª¨ë‘ ì°¨ë‹¨í•©ë‹ˆë‹¤.', + 'status_guest' => 'ì†ë‹˜', + 'status_activated' => '활성화 ìƒíƒœ', + 'status_registered' => '등ë¡í•œ', + ], + 'group' => [ + 'label' => '그룹', + 'id' => 'ì•„ì´ë””', + 'name' => 'ì´ë¦„', + 'description_field' => '설명', + 'code' => '코드', + 'code_comment' => 'ì´ ê·¸ë£¹ì„ ì‹ë³„하는 ë° ì‚¬ìš©ë˜ëŠ” 고유 한 코드를 입력하십시오.', + 'created_at' => 'ìƒì„±ë‚ ì§œ', + 'users_count' => 'ì‚¬ìš©ìž ìˆ˜' + ], + 'groups' => [ + 'menu_label' => '그룹 목ë¡', + 'all_groups' => 'íšŒì› ê·¸ë£¹ 목ë¡', + 'new_group' => '새로운 그룹', + 'delete_selected_confirm' => 'ì„ íƒí•œ ê·¸ë£¹ì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?', + 'list_title' => '그룹 관리', + 'delete_confirm' => 'ì´ ê·¸ë£¹ì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?', + 'delete_selected_success' => 'ì„ íƒí•œ ê·¸ë£¹ì„ ì„±ê³µì ìœ¼ë¡œ 삭제했습니다.', + 'delete_selected_empty' => 'ì„ íƒëœ ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤.', + 'return_to_list' => '그룹 목ë¡ìœ¼ë¡œ ëŒì•„가기', + 'return_to_users' => 'ì‚¬ìš©ìž ëª©ë¡ìœ¼ë¡œ ëŒì•„가기', + 'create_title' => 'ì‚¬ìš©ìž ê·¸ë£¹ ìƒì„±', + 'update_title' => 'ì‚¬ìš©ìž ê·¸ë£¹ 수정', + 'preview_title' => 'ì‚¬ìš©ìž ê·¸ë£¹ 미리 보기', + ], + 'login' => [ + 'attribute_email' => 'ì´ë©”ì¼', + 'attribute_username' => '회ì›ëª…', + ], + 'account' => [ + 'account' => '계정', + 'account_desc' => 'ì‚¬ìš©ìž ê´€ë¦¬ í¼', + 'banned' => '죄송합니다. ì´ ì‚¬ìš©ìžëŠ” 현재 활성화ë˜ì–´ 있지 않습니다. ë„ì›€ì´ í•„ìš”í•˜ì‹œë©´ ì €í¬ì—게 ì—°ë½ ì£¼ì‹­ì‹œì˜¤.', + 'redirect_to' => '리디렉션', + 'redirect_to_desc' => '로그ì¸, 등ë¡, ì—…ë°ì´íЏ 후 리디렉션 í•  페ì´ì§€ ì´ë¦„.', + 'code_param' => '활성화 코드 ê°’', + 'code_param_desc' => 'ë“±ë¡ í™œì„±í™” ì½”ë“œì— ì‚¬ìš©ë˜ëŠ” 페ì´ì§€ URL파ë¼ë¯¸í„°', + 'force_secure' => 'ê°•ì œ 보안 프로토콜', + 'force_secure_desc' => 'í•­ìƒ URLì„ HTTPS스키마로 리디렉션 하십시오.', + 'invalid_user' => '지정한 ìžê²© ì¦ëª…ì„ ê°€ì§„ 사용ìžë¥¼ ì°¾ì„ ìˆ˜ 없습니다.', + 'invalid_activation_code' => 'ì œê³µëœ í™œì„±í™” 코드가 잘못ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'invalid_deactivation_pass' => '입력한 암호가 잘못ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'success_activation' => 'ê³„ì •ì´ í™œì„±í™”ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'success_deactivation' => 'ê³„ì •ì´ ë¹„í™œì„±í™”ë˜ì—ˆìŠµë‹ˆë‹¤. 죄송합니다!', + 'success_saved' => 'ì„¤ì •ì´ ì„±ê³µì ìœ¼ë¡œ 저장ë˜ì—ˆìŠµë‹ˆë‹¤!', + 'login_first' => '먼저 로그ì¸í•´ì•¼ 합니다!', + 'already_active' => 'ê³„ì •ì´ ì´ë¯¸ 활성화ë˜ì—ˆìŠµë‹ˆë‹¤!', + 'activation_email_sent' => '활성화 ì´ë©”ì¼ì´ 사용ìžì˜ ì´ë©”ì¼ ì£¼ì†Œë¡œ 전송ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'registration_disabled' => 'ê°€ìž…ì´ í˜„ìž¬ 비활성화ë˜ì–´ 있습니다.', + 'sign_in' => '로그ì¸', + 'register' => '회ì›ê°€ìž…', + 'full_name' => 'ì „ì²´ ì´ë¦„', + 'email' => 'ì´ë©”ì¼', + 'password' => '비밀번호', + 'login' => '로그ì¸.', + 'new_password' => '새 암호', + 'new_password_confirm' => '암호 재확ì¸', + ], + 'reset_password' => [ + 'reset_password' => '비밀번호 재설정', + 'reset_password_desc' => '암호 형ì‹ì„ 잊어 버렸습니다.', + 'code_param' => '코드 매개 변수 재설정', + 'code_param_desc' => '재설정 ì½”ë“œì— ì‚¬ìš©ë˜ëŠ” 페ì´ì§€ URL매개 변수', + ], + 'session' => [ + 'session' => '기간', + 'session_desc' => '페ì´ì§€ì— ì‚¬ìš©ìž ì„¸ì…˜ì„ ì¶”ê°€í•˜ê³  페ì´ì§€ 액세스를 제한할 수 있습니다.', + 'security_title' => '허용', + 'security_desc' => '누가 ì´ íŽ˜ì´ì§€ì— 액세스 í•  수 있습니까?', + 'all' => '모든.', + 'users' => '사용ìž', + 'guests' => '방문ìž', + 'allowed_groups_title' => '그룹 허용', + 'allowed_groups_description' => '허용ë˜ëŠ” ê·¸ë£¹ì„ ì„ íƒí•˜ê±°ë‚˜, 모든 ê·¸ë£¹ì„ í—ˆìš©í•  ê·¸ë£¹ì´ ì—†ë„ë¡ ì„ íƒí•˜ì‹­ì‹œì˜¤.', + 'redirect_title' => '리디렉션', + 'redirect_desc' => '액세스가 ê±°ë¶€ëœ ê²½ìš° 리디렉션 í•  페ì´ì§€ ì´ë¦„입니다.', + 'logout' => '성공ì ìœ¼ë¡œ 로그아웃ë˜ì—ˆìŠµë‹ˆë‹¤!', + 'stop_impersonate_success' => 'ë” ì´ìƒ 사용ìžë¥¼ 가장하지 않습니다.', + ] +]; diff --git a/plugins/rainlab/user/lang/nl/lang.php b/plugins/rainlab/user/lang/nl/lang.php new file mode 100644 index 0000000..486406b --- /dev/null +++ b/plugins/rainlab/user/lang/nl/lang.php @@ -0,0 +1,224 @@ + [ + 'name' => 'Gebruiker', + 'description' => 'Gebruikersbeheer voor de front-end.', + 'tab' => 'Gebruikers', + 'access_users' => 'Beheer Gebruikers', + 'access_groups' => 'Beheer Groepen', + 'access_settings' => 'Gebruikersinstellingen beheren', + 'impersonate_user' => 'Inloggen als gebruikers', + ], + 'users' => [ + 'menu_label' => 'Gebruikers', + 'all_users' => 'Alle gebruikers', + 'new_user' => 'Nieuwe gebruiker', + 'list_title' => 'Beheer gebruikers', + 'trashed_hint_title' => 'Gebruiker heeft zijn account gedeactiveerd', + 'trashed_hint_desc' => 'Deze gebruiker heeft zijn account gedeactiveerd en wil niet meer op de site verschijnen. Hij kan zijn account op elk moment herstellen door opnieuw in te loggen.', + 'banned_hint_title' => 'Gebruiker is verbannen', + 'banned_hint_desc' => 'Deze gebruiker is verbannen door een beheerder en kan niet meer inloggen.', + 'guest_hint_title' => 'Dit is een gastgebruiker', + 'guest_hint_desc' => 'Deze gebruiker wordt alleen voor referentiedoeleinden opgeslagen en moet zich registreren voordat hij zich aanmeldt.', + 'activate_warning_title' => 'Gebruiker is niet geactiveerd!', + 'activate_warning_desc' => 'Deze gebruiker is niet geactiveerd en kan niet inloggen.', + 'activate_confirm' => 'Weet u zeker dat u het gebruikersaccount wilt activeren?', + 'activated_success' => 'Gebruikersaccount succesvol geactiveerd!', + 'activate_manually' => 'Deze gebruiker handmatig activeren', + 'convert_guest_confirm' => 'Deze gast omzetten naar een gebruiker?', + 'convert_guest_manually' => 'Omzetten naar geregistreerde gebruiker', + 'convert_guest_success' => 'Gebruiker is omgezet naar een geregistreerd account', + 'impersonate_user' => 'Inloggen als', + 'impersonate_confirm' => 'Als deze gebruiker inloggen? U kunt terugkeren naar uw oorspronkelijke staat door uit te loggen.', + 'impersonate_success' => 'Je bent nu ingelogd als deze gebruiker', + 'delete_confirm' => 'Weet u zeker dat u deze gebruiker wilt verwijderen?', + 'unban_user' => 'Deblokkeer deze gebruiker', + 'unban_confirm' => 'Wil je deze gebruiker echt deblokkeren?', + 'unbanned_success' => 'Gebruiker is gedeblokkeerd', + 'return_to_list' => 'Terug naar overzicht', + 'update_details' => 'Details bijwerken', + 'bulk_actions' => 'Bulk acties', + 'delete_selected' => 'Geselecteerde verwijderen', + 'delete_selected_confirm' => 'Verwijder geselecteerde gebruikers?', + 'delete_selected_empty' => 'Er zijn geen geselecteerde gebruikers om te verwijderen.', + 'delete_selected_success' => 'Geselecteerde gebruikers verwijderd.', + 'activate_selected' => 'Activeer geselecteerde', + 'activate_selected_confirm' => 'De geselecteerde gebruikers activeren?', + 'activate_selected_empty' => 'Er zijn geen geselecteerde gebruikers om te activeren.', + 'activate_selected_success' => 'Geselecteerde gebruikers zijn succesvol geactiveerd.', + 'deactivate_selected' => 'Deactiveer geselecteerde', + 'deactivate_selected_confirm' => 'De geselecteerde gebruikers deactiveren?', + 'deactivate_selected_empty' => 'There are no selected users to deactivate.', + 'deactivate_selected_success' => 'Geselecteerde gebruikers zijn succesvol gedeactiveerd.', + 'restore_selected' => 'Herstel geselecteerde', + 'restore_selected_confirm' => 'De geselecteerde gebruikers herstellen?', + 'restore_selected_empty' => 'Er zijn geen geselecteerde gebruikers om te herstellen.', + 'restore_selected_success' => 'Geselecteerde gebruikers zijn succesvol hersteld.', + 'ban_selected' => 'Blokkeer geselecteerde', + 'ban_selected_confirm' => 'De geselecteerde gebruikers blokkeren?', + 'ban_selected_empty' => 'Er zijn geen gebruikers geselecteerd om te blokkeren.', + 'ban_selected_success' => 'Geselecteerde gebruikers zijn succesvol geblokkeerd.', + 'unban_selected' => 'Deblokkeer geselecteerde', + 'unban_selected_confirm' => 'De geselecteerde gebruikers deblokkeren?', + 'unban_selected_empty' => 'Er zijn geen gebruikers geselecteerd om te deblokkeren.', + 'unban_selected_success' => 'Geselecteerde gebruikers zijn succesvol gedeblokkeerd.', + 'unsuspend' => 'Blokkade opheffen', + 'unsuspend_success' => 'Blokkade voor de gebruiker is opgeheven.', + 'unsuspend_confirm' => 'Blokkade voor deze gebruiker opheffen?', + ], + 'settings' => [ + 'users' => 'Gebruikers', + 'menu_label' => 'Instellingen', + 'menu_description' => 'Beheer de instellingen voor gebruikers.', + 'activation_tab' => 'Activatie', + 'signin_tab' => 'Inloggen', + 'registration_tab' => 'Registratie', + 'profile_tab' => 'Profiel', + 'notifications_tab' => 'Notificaties', + 'allow_registration' => 'Gebruikersregistratie toestaan', + 'allow_registration_comment' => 'Als deze optie is uitgeschakeld kunnen alleen beheerders gebruikers aanmaken.', + 'activate_mode' => 'Activatie modus', + 'activate_mode_comment' => 'Selecteer de wijze waarop een gebruikersaccount geactiveerd moet te worden.', + 'activate_mode_auto' => 'Automatisch', + 'activate_mode_auto_comment' => 'Het gebruikersaccount wordt meteen geactiveerd na registratie.', + 'activate_mode_user' => 'Gebruiker', + 'activate_mode_user_comment' => 'De gebruiker activeert het account d.m.v. e-mail.', + 'activate_mode_admin' => 'Beheerder', + 'activate_mode_admin_comment' => 'Alleen de beheerder kan het gebruikersaccount activeren.', + 'require_activation' => 'Inloggen vereist activatie', + 'require_activation_comment' => 'Gebruikers moeten een geactiveerd account hebben.', + 'use_throttle' => 'Beperk inlogpogingen', + 'use_throttle_comment' => 'Meerdere mislukte inlog pogingen resulteren in een tijdelijk uitgeschakeld gebruikersaccount.', + 'use_register_throttle' => 'Registraties beperken', + 'use_register_throttle_comment' => 'Voorkomen dat meerdere registraties van hetzelfde IP kort na elkaar plaatsvinden.', + 'block_persistence' => 'Voorkom gelijktijdige sessies ', + 'block_persistence_comment' => 'Indien ingeschakeld kunnen gebruikers zich niet aanmelden op meerdere apparaten tegelijk.', + 'login_attribute' => 'Inlog attribuut', + 'login_attribute_comment' => 'Selecteer het attribuut wat moet worden gebruikt om in te loggen.', + 'remember_login' => 'Onthoud inlogmodus', + 'remember_login_comment' => 'Selecteer of de gebruikerslogin onthouden moet worden.', + 'remember_always' => 'Altijd', + 'remember_never' => 'Nooit', + 'remember_ask' => 'Vraag de gebruiker bij het inloggen', + ], + 'user' => [ + 'label' => 'Gebruiker', + 'id' => 'ID', + 'username' => 'Gebruikersnaam', + 'name' => 'Voornaam', + 'name_empty' => 'Anoniem', + 'surname' => 'Achternaam', + 'email' => 'E-mailadres', + 'created_at' => 'Geregistreerd op', + 'last_seen' => 'Laatste login', + 'is_guest' => 'Gast', + 'joined' => 'Geregistreerd op', + 'is_online' => 'Momenteel online', + 'is_offline' => 'Momenteel offline', + 'send_invite' => 'Uitnodiging per e-mail sturen', + 'send_invite_comment' => 'Stuurt een welkomstbericht met login en wachtwoord informatie.', + 'create_password' => 'Wachtwoord aanmaken', + 'create_password_comment' => 'Voer een nieuw wachtwoord in dat wordt gebruikt om in te loggen.', + 'reset_password' => 'Reset wachtwoord', + 'reset_password_comment' => 'Voer een nieuw wachtwoord in om het wachtwoord te resetten.', + 'confirm_password' => 'Herhaal wachtwoord', + 'confirm_password_comment' => 'Voer het wachtwoord nogmaals in.', + 'groups' => 'Groep', + 'empty_groups' => 'Er zijn geen gebruikersgroepen beschikbaar.', + 'avatar' => 'Profielfoto', + 'details' => 'Details', + 'account' => 'Account', + 'block_mail' => 'Blokkeert alle uitgaande mail die naar deze gebruiker wordt gestuurd.', + 'status_guest' => 'Gast', + 'status_activated' => 'Geactiveerd', + 'status_registered' => 'Geregistreerd', + 'created_ip_address' => 'Registratie IP-address', + 'last_ip_address' => 'Laatste IP-address', + ], + 'group' => [ + 'label' => 'Groep', + 'id' => 'ID', + 'name' => 'Naam', + 'description_field' => 'Omschrijving', + 'code' => 'Code', + 'code_comment' => 'Voer een unieke code in als je deze groep wilt gebruiken met de API.', + 'created_at' => 'Aangemaakt op', + 'users_count' => 'Gebruikers', + 'is_new_user_default_field' => 'Voeg nieuwe beheerders automatisch toe aan deze groep.', + ], + 'groups' => [ + 'menu_label' => 'Groepen', + 'all_groups' => 'Groepen', + 'new_group' => 'Nieuwe groep', + 'delete_selected_confirm' => 'Weet u zeker dat u de geselecteerde groepen wilt verwijderen?', + 'list_title' => 'Beheer groepen', + 'delete_confirm' => 'Weet u zeker dat u deze groep wilt verwijderen?', + 'delete_selected_success' => 'De geselecteerde groepen zijn verwijderd.', + 'delete_selected_empty' => 'Er zijn geen groepen geselecteerd om te verwijderen.', + 'return_to_list' => 'Terug naar overzicht', + 'return_to_users' => 'Back to users list', + 'create_title' => 'Groep aanmaken', + 'update_title' => 'Wijzig groep', + 'preview_title' => 'Voorbeeldweergave groep', + ], + 'login' => [ + 'attribute_email' => 'E-mailadres', + 'attribute_username' => 'Gebruikersnaam', + ], + 'account' => [ + 'account' => 'Account', + 'account_desc' => 'Gebruikersaccount formulier.', + 'banned' => 'Sorry, deze gebruiker is momenteel niet geactiveerd. Neem contact met ons op voor verdere hulp.', + 'redirect_to' => 'Redirect naar', + 'redirect_to_desc' => 'Pagina om naar te redirecten na het bijwerken, inloggen of registreren.', + 'code_param' => 'Activatie Code parameter', + 'code_param_desc' => 'De pagina URL parameter die gebruikt wordt voor de registratie activatie code.', + 'force_secure' => 'Forceer beveiligd protocol', + 'force_secure_desc' => 'Stuur de URL altijd door naar HTTPS.', + 'invalid_user' => 'Geen gebruiker gevonden.', + 'invalid_activation_code' => 'Onjuiste activatie code', + 'invalid_deactivation_pass' => 'Het ingevoerde wachtwoord is ongeldig.', + 'invalid_current_pass' => 'Het ingevoerde huidige wachtwoord is ongeldig.', + 'success_activation' => 'Uw account is succesvol geactiveerd.', + 'success_deactivation' => 'Succesvol je account gedeactiveerd. Jammer dat je weggaat!', + 'success_saved' => 'Instellingen zijn opgeslagen.', + 'login_first' => 'U moet ingelogd zijn om deze pagina te bekijken.', + 'already_active' => 'Uw gebruikersaccount is reeds geactiveerd.', + 'activation_email_sent' => 'Een e-mailbericht met een activatie link is naar uw e-mailadres verzonden.', + 'activation_by_admin' => 'U bent succesvol geregistreerd. Uw account is nog niet actief en moet worden goedgekeurd door een beheerder.', + 'registration_disabled' => 'Registratie is momenteel uitgeschakeld.', + 'registration_throttled' => 'Registratie is geblokkeerd. Probeer het later nog eens.', + 'sign_in' => 'Inloggen', + 'register' => 'Registreren', + 'full_name' => 'Volledige naam', + 'email' => 'E-mailadres', + 'password' => 'Wachtwoord', + 'login' => 'Inloggen', + 'new_password' => 'Nieuw wachtwoord', + 'new_password_confirm' => 'Herhaal nieuw wachtwoord', + 'update_requires_password' => 'Bevestig wachtwoord bij update', + 'update_requires_password_comment' => 'Vereis het huidige wachtwoord van de gebruiker wanneer hij zijn profiel wijzigt.', + ], + 'reset_password' => [ + 'reset_password' => 'Reset wachtwoord', + 'reset_password_desc' => 'Wachtwoord vergeten formulier.', + 'code_param' => 'Reset Code parameter', + 'code_param_desc' => 'De pagina URL parameter die gebruikt wordt voor de reset code.', + ], + 'session' => [ + 'session' => 'Sessie', + 'session_desc' => 'Voegt de gebruikerssessie toe aan een pagina om pagina toegang te beperken.', + 'security_title' => 'Alleen toegestaan voor', + 'security_desc' => 'Wie toegestaan is om de pagina te bekijken.', + 'all' => 'Alle', + 'users' => 'Gebruikers', + 'guests' => 'Gasten', + 'allowed_groups_title' => 'Toegestane groepen', + 'allowed_groups_description' => 'Kies toegelaten groepen of geen om alle groepen toe te laten', + 'redirect_title' => 'Redirect naar', + 'redirect_desc' => 'Pagina om naar te redirecten als toegang is afgewezen.', + 'logout' => 'U bent succesvol uitgelogd.', + 'stop_impersonate_success' => 'Je doet je niet langer voor als een gebruiker.', + ], +]; diff --git a/plugins/rainlab/user/lang/pl/lang.php b/plugins/rainlab/user/lang/pl/lang.php new file mode 100644 index 0000000..5959c3b --- /dev/null +++ b/plugins/rainlab/user/lang/pl/lang.php @@ -0,0 +1,205 @@ + [ + 'name' => 'Użytkownik', + 'description' => 'ZarzÄ…dzanie użytkownikami.', + 'tab' => 'Użytkownicy', + 'access_users' => 'ZarzÄ…dzaj użytkownikami', + 'access_groups' => 'ZarzÄ…dzaj grupami użytkowników', + 'access_settings' => 'ZarzÄ…dzaj ustawieniami użytkownika', + 'impersonate_user' => 'Wcielaj siÄ™ w użytkowników' + ], + 'users' => [ + 'menu_label' => 'Użytkownicy', + 'all_users' => 'Wszyscy użytkownicy', + 'new_user' => 'Nowy użytkownik', + 'list_title' => 'ZarzÄ…dzaj użytkownikami', + 'trashed_hint_title' => 'Użytkownik dezaktywowaÅ‚ swoje konto', + 'trashed_hint_desc' => 'Ten użytkownik dezaktywowaÅ‚ swoje konto i nie chce już wyÅ›wietlać siÄ™ na stronie. Może przywrócić konto w dowolnym momencie, logujÄ…c siÄ™ z powrotem.', + 'banned_hint_title' => 'Użytkownik zostaÅ‚ zbanowany', + 'banned_hint_desc' => 'Ten użytkownik zostaÅ‚ zbanowany przez administratora i nie bÄ™dzie mógÅ‚ siÄ™ zalogować.', + 'guest_hint_title' => 'To jest użytkownik goÅ›cinny', + 'guest_hint_desc' => 'Ten użytkownik jest przechowywany wyłącznie w celach informacyjnych i musi siÄ™ zarejestrować przed zalogowaniem.', + 'activate_warning_title' => 'Użytkownik nie aktywowany!', + 'activate_warning_desc' => 'Ten użytkownik nie zostaÅ‚ aktywowany i może nie być w stanie siÄ™ zalogować.', + 'activate_confirm' => 'Czy na pewno chcesz aktywować tego użytkownika?', + 'activated_success' => 'Użytkownik zostaÅ‚ aktywowany', + 'activate_manually' => 'Aktywuj tego użytkownika rÄ™cznie', + 'convert_guest_confirm' => 'Konwertuj tego goÅ›cia do użytkownika?', + 'convert_guest_manually' => 'Konwertuj na zarejestrowanego użytkownika', + 'convert_guest_success' => 'Użytkownik zostaÅ‚ przekonwertowany na zarejestrowanego', + 'impersonate_user' => 'Wciel siÄ™ w użytkownika', + 'impersonate_confirm' => 'Wcielić siÄ™ w tego użytkownika? Możesz powrócić do pierwotnego stanu wylogowujÄ…c siÄ™.', + 'impersonate_success' => 'Wcielasz siÄ™ w tego użytkownika', + 'delete_confirm' => 'Czy na pewno chcesz usunąć tego użytkownika?', + 'unban_user' => 'Odbanuj tego użytkownika', + 'unban_confirm' => 'Czy na pewno chcesz odbanować tego użytkownika?', + 'unbanned_success' => 'Użytkownik zostaÅ‚ odbanowany', + 'return_to_list' => 'Wróć do listy użytkowników', + 'update_details' => 'Zaktualizuj szczegóły', + 'bulk_actions' => 'DziaÅ‚ania masowe', + 'delete_selected' => 'UsuÅ„ wybrane', + 'delete_selected_confirm' => 'Usunąć wybranych użytkowników?', + 'delete_selected_empty' => 'Nie ma wybranych użytkowników do usuniÄ™cia.', + 'delete_selected_success' => 'PomyÅ›lnie usuniÄ™to wybranych użytkowników.', + 'activate_selected' => 'Aktywuj wybranych', + 'activate_selected_confirm' => 'Aktywować wybranych użytkowników?', + 'activate_selected_empty' => 'Nie ma wybranych użytkowników do aktywacji.', + 'activate_selected_success' => 'PomyÅ›lnie aktywowano wybranych użytkowników.', + 'deactivate_selected' => 'Dezaktywuj wybranych', + 'deactivate_selected_confirm' => 'Dezaktywować wybranych użytkowników?', + 'deactivate_selected_empty' => 'Nie ma wybranych użytkowników do dezaktywacji.', + 'deactivate_selected_success' => 'PomyÅ›lnie dezaktywowano wybranych użytkowników.', + 'restore_selected' => 'Przywrócić wybranych', + 'restore_selected_confirm' => 'Przywrócić wybranych użytkowników?', + 'restore_selected_empty' => 'Nie ma wybranych użytkowników do przywrócenia.', + 'restore_selected_success' => 'PomyÅ›lnie przywrócono wybranych użytkowników.', + 'ban_selected' => 'Zbanuj wybranych', + 'ban_selected_confirm' => 'Zbanować wybranych użytkowników?', + 'ban_selected_empty' => 'Nie ma wybranych użytkowników do banowania.', + 'ban_selected_success' => 'Z powodzeniem zbanowano wybranych użytkowników.', + 'unban_selected' => 'Odbanuj wybranych', + 'unban_selected_confirm' => 'Odbanować wybranych użytkowników?', + 'unban_selected_empty' => 'Nie ma wybranych użytkowników do odbanowania.', + 'unban_selected_success' => 'Z powodzeniem odbanowano wybranych użytkowników.', + ], + 'settings' => [ + 'users' => 'Użytkownicy', + 'menu_label' => 'Ustawienia użytkownika', + 'menu_description' => 'ZarzÄ…dzaj ogólnymi ustawieniami dla użytkowników.', + 'activation_tab' => 'Aktywacja', + 'signin_tab' => 'Zaloguj siÄ™', + 'registration_tab' => 'Rejestracja', + 'notifications_tab' => 'Powiadomienia', + 'allow_registration' => 'Zezwalaj na rejestracjÄ™ użytkownika', + 'allow_registration_comment' => 'JeÅ›li jest to wyłączone, użytkownicy mogÄ… być tworzeni tylko przez administratorów.', + 'activate_mode' => 'Tryb aktywacji', + 'activate_mode_comment' => 'Wybierz sposób aktywacji konta użytkownika.', + 'activate_mode_auto' => 'Automatyczny', + 'activate_mode_auto_comment' => 'Aktywowani automatycznie po rejestracji.', + 'activate_mode_user' => 'Użytkownik', + 'activate_mode_user_comment' => 'Użytkownik aktywuje wÅ‚asne konto za pomocÄ… poczty e-mail.', + 'activate_mode_admin' => 'Administrator', + 'activate_mode_admin_comment' => 'Tylko administrator może aktywować użytkownika.', + 'require_activation' => 'Logowanie wymaga aktywacji konta', + 'require_activation_comment' => 'Użytkownicy muszÄ… mieć aktywne konto, aby siÄ™ zalogować.', + 'use_throttle' => 'Blokada prób logowania', + 'use_throttle_comment' => 'Powtórne nieudane próby zalogowania tymczasowo zawieszajÄ… użytkownika.', + 'block_persistence' => 'Zapobiegaj równolegÅ‚ym sesjom', + 'block_persistence_comment' => 'Aktywni użytkownicy nie mogÄ… zalogować siÄ™ na wielu urzÄ…dzeniach w tym samym czasie.', + 'login_attribute' => 'Dane do logowania', + 'login_attribute_comment' => 'Wybierz, jakie podstawowe dane użytkownika majÄ… być używane do logowania.', + ], + 'user' => [ + 'label' => 'Użytkownik', + 'id' => 'ID', + 'username' => 'Nazwa użytkownika', + 'name' => 'ImiÄ™ / nick', + 'name_empty' => 'Anonimowy', + 'surname' => 'Nazwisko', + 'email' => 'Email', + 'created_at' => 'Zarejestrowany', + 'last_seen' => 'Ostatnio widziany', + 'is_guest' => 'Gość', + 'joined' => 'DołączyÅ‚', + 'is_online' => 'Online', + 'is_offline' => 'Offline', + 'send_invite' => 'WyÅ›lij zaproszenie pocztÄ… e-mail', + 'send_invite_comment' => 'WysyÅ‚a wiadomość powitalnÄ… zawierajÄ…cÄ… dane logowania i hasÅ‚o.', + 'create_password' => 'Stwórz hasÅ‚o', + 'create_password_comment' => 'Wprowadź nowe hasÅ‚o używane do logowania.', + 'reset_password' => 'Zresetuj hasÅ‚o', + 'reset_password_comment' => 'Aby zresetować hasÅ‚o użytkownika, wprowadź nowe hasÅ‚o.', + 'confirm_password' => 'Potwierdzenie hasÅ‚a', + 'confirm_password_comment' => 'Wprowadź ponownie hasÅ‚o, aby je potwierdzić.', + 'groups' => 'Grupy', + 'empty_groups' => 'Brak dostÄ™pnych grup użytkowników.', + 'avatar' => 'Avatar', + 'details' => 'Szczegóły', + 'account' => 'Konto', + 'block_mail' => 'Zablokuj wszystkie wiadomoÅ›ci wychodzÄ…ce wysyÅ‚ane do tego użytkownika.', + 'status_guest' => 'Gość', + 'status_activated' => 'Aktywowany', + 'status_registered' => 'Zarejestrowany', + ], + 'group' => [ + 'label' => 'Grupa', + 'id' => 'ID', + 'name' => 'Nazwa', + 'description_field' => 'Opis', + 'code' => 'Kod', + 'code_comment' => 'Wpisz unikalny kod sÅ‚użący do identyfikacji tej grupy.', + 'created_at' => 'Utworzona', + 'users_count' => 'Użytkownicy' + ], + 'groups' => [ + 'menu_label' => 'Grupy', + 'all_groups' => 'Grupy użytkowników', + 'new_group' => 'Nowa grupa', + 'delete_selected_confirm' => 'Czy na pewno chcesz usunąć wybrane grupy?', + 'list_title' => 'ZarzÄ…dzaj grupami', + 'delete_confirm' => 'Czy na pewno chcesz usunąć tÄ™ grupÄ™?', + 'delete_selected_success' => 'PomyÅ›lnie usuniÄ™to wybrane grupy.', + 'delete_selected_empty' => 'Brak wybranych grup do usuniÄ™cia.', + 'return_to_list' => 'Powrót do listy grup', + 'return_to_users' => 'Powrót do listy użytkowników', + 'create_title' => 'Utwórz grupÄ™ użytkowników', + 'update_title' => 'Edytuj grupÄ™ użytkowników', + 'preview_title' => 'Podejrzyj grupÄ™ użytkowników' + ], + 'login' => [ + 'attribute_email' => 'Email', + 'attribute_username' => 'Nazwa użytkownika' + ], + 'account' => [ + 'account' => 'Konto', + 'account_desc' => 'Formularz zarzÄ…dzania użytkownikiem.', + 'banned' => 'Przepraszamy, ten użytkownik jest obecnie nieaktywny. Skontaktuj siÄ™ z nami, aby uzyskać dalszÄ… pomoc.', + 'redirect_to' => 'Przekieruj do', + 'redirect_to_desc' => 'Nazwa strony do przekierowania po aktualizacji, zalogowaniu lub rejestracji.', + 'code_param' => 'Kod aktywacyjny - parametr', + 'code_param_desc' => 'Parametr URL strony używany do rejestracji', + 'force_secure' => 'WymuÅ› bezpieczny protokół', + 'force_secure_desc' => 'Zawsze przekierowuj adres URL ze schematem HTTPS.', + 'invalid_user' => 'Nie znaleziono użytkownika o podanych danych uwierzytelniajÄ…cych.', + 'invalid_activation_code' => 'Podano niepoprawny kod aktywacyjny.', + 'invalid_deactivation_pass' => 'Podane hasÅ‚o jest nieprawidÅ‚owe.', + 'success_activation' => 'PomyÅ›lnie aktywowaÅ‚eÅ› swoje konto.', + 'success_deactivation' => 'PomyÅ›lnie dezaktywowaliÅ›my Twoje konto.', + 'success_saved' => 'Ustawienia zostaÅ‚y zapisane!', + 'login_first' => 'Musisz siÄ™ najpierw zalogować!', + 'already_active' => 'Twoje konto jest już aktywowane!', + 'activation_email_sent' => 'Email aktywacyjny zostaÅ‚ wysÅ‚any na twój adres e-mail.', + 'registration_disabled' => 'Rejestracja jest obecnie wyłączona.', + 'sign_in' => 'Zaloguj siÄ™', + 'register' => 'Rejestracja', + 'full_name' => 'ImiÄ™', + 'email' => 'Email', + 'password' => 'HasÅ‚o', + 'login' => 'Login', + 'new_password' => 'Nowe hasÅ‚o', + 'new_password_confirm' => 'Potwierdź nowe hasÅ‚o' + ], + 'reset_password' => [ + 'reset_password' => 'Zresetuj hasÅ‚o', + 'reset_password_desc' => 'Formularz zapomnianego hasÅ‚a.', + 'code_param' => 'Kod do resetu hasÅ‚a - parametr', + 'code_param_desc' => 'Parametr URL strony używany do resetu hasÅ‚a' + ], + 'session' => [ + 'session' => 'Sesja', + 'session_desc' => 'Dodaje sesjÄ™ użytkownika do strony i może ograniczyć dostÄ™p do strony.', + 'security_title' => 'Zezwól tylko', + 'security_desc' => 'Kto ma dostÄ™p do tej strony.', + 'all' => 'Wszyscy', + 'users' => 'Użytkownicy', + 'guests' => 'GoÅ›cie', + 'allowed_groups_title' => 'Zezwól grupom', + 'allowed_groups_description' => 'Wybierz dozwolone grupy lub brak grup, aby umożliwić wszystkim grupom', + 'redirect_title' => 'Przekieruj do', + 'redirect_desc' => 'Nazwa strony do przekierowania w przypadku odmowy dostÄ™pu.', + 'logout' => 'WylogowaÅ‚eÅ› siÄ™ poprawnie!', + 'stop_impersonate_success' => 'Nie wcielasz siÄ™ już w użytkownika.', + ] +]; diff --git a/plugins/rainlab/user/lang/pt-br/lang.php b/plugins/rainlab/user/lang/pt-br/lang.php new file mode 100644 index 0000000..7341423 --- /dev/null +++ b/plugins/rainlab/user/lang/pt-br/lang.php @@ -0,0 +1,189 @@ + [ + 'name' => 'Usuário', + 'description' => 'Gerenciamento de usuários de front-end.', + 'tab' => 'Usuário', + 'access_users' => 'Gerenciar usuários', + 'access_groups' => 'Gerenciar Grupos de Usuários', + 'access_settings' => 'Gerenciar configurações do usuário' + ], + 'users' => [ + 'menu_label' => 'Usuários', + 'all_users' => 'Todos os Usuários', + 'new_user' => 'Novo Usuário', + 'list_title' => 'Gerenciar Usuários', + 'trashed_hint_title' => 'O usuário desativou sua conta', + 'trashed_hint_desc' => 'Este usuário desativou sua conta e não quer mais aparecer no site. Eles podem restaurar sua conta a qualquer momento, fazendo login novamente.', + 'banned_hint_title' => 'O usuário foi banido', + 'banned_hint_desc' => 'Este usuário foi banido por um administrador e não poderá iniciar sessão.', + 'guest_hint_title' => 'Este é um usuário convidado', + 'guest_hint_desc' => 'Esse usuário é armazenado apenas para fins de referência e precisa se registrar antes de fazer login.', + 'activate_warning_title' => 'Usuário não ativado!', + 'activate_warning_desc' => 'Este usuário ainda não foi ativado e pode ser incapaz de fazer login.', + 'activate_confirm' => 'Deseja realmente ativar este usuário?', + 'activated_success' => 'O usuário foi ativado', + 'activate_manually' => 'Ativar este usuário manualmente', + 'convert_guest_confirm' => 'Converter este convidado para um usuário?', + 'convert_guest_manually' => 'Converter para usuário registrado', + 'convert_guest_success' => 'O usuário foi convertido em uma conta registrada', + 'delete_confirm' => 'Deseja mesmo excluir este usuário?', + 'unban_user' => 'Desbanir este usuário', + 'unban_confirm' => 'Você realmente quer desbanir este usuário?', + 'unbanned_success' => 'O usuário foi desbanido', + 'return_to_list' => 'Voltar à lista de usuários', + 'update_details' => 'Atualizar detalhes', + 'bulk_actions' => 'Ações em massa', + 'delete_selected' => 'Excluir selecionado', + 'delete_selected_confirm' => 'Excluir os usuários selecionados?', + 'delete_selected_empty' => 'Não há usuários selecionados a serem excluídos.', + 'delete_selected_success' => 'Os usuários selecionados foram excluídos com êxito.', + 'deactivate_selected' => 'Desativar selecionado', + 'deactivate_selected_confirm' => 'Desativar os usuários selecionados?', + 'deactivate_selected_empty' => 'Não há usuários selecionados para desativar.', + 'deactivate_selected_success' => 'Os Usuários selecionados foram desativados com sucesso.', + 'restore_selected' => 'Restaurar selecionado', + 'restore_selected_confirm' => 'Restaurar usuários selecionados?', + 'restore_selected_empty' => 'Não há usuários selecionados para restaurar.', + 'restore_selected_success' => 'Os usuários selecionados foram restaurado com sucesso.', + 'ban_selected' => 'Banir selecionado', + 'ban_selected_confirm' => 'Banir os usuários selecionados?', + 'ban_selected_empty' => 'Não há usuários selecionados para banir.', + 'ban_selected_success' => 'Os usuários selecionados foram banidos com sucesso', + 'unban_selected' => 'Desbanir selecionado', + 'unban_selected_confirm' => 'Desbanir os usuários selecionados?', + 'unban_selected_empty' => 'Não há usuários selecionados para desbanir.', + 'unban_selected_success' => 'Os usuários selecionados foram desbanidos com sucesso.', + ], + 'settings' => [ + 'users' => 'Usuários', + 'menu_label' => 'Configurações de usuário', + 'menu_description' => 'Gerenciar configurações relacionadas a usuários.', + 'activation_tab' => 'Ativação', + 'signin_tab' => 'Login', + 'registration_tab' => 'Registração', + 'notifications_tab' => 'Notificações', + 'allow_registration' => 'Permitir o registro do usuário', + 'allow_registration_comment' => 'Se isso estiver desabilitado, os usuários só podem ser criados por administradores.', + 'activate_mode' => 'Modo de ativação', + 'activate_mode_comment' => 'Selecione como uma conta de usuário deve ser ativada.', + 'activate_mode_auto' => 'Automática', + 'activate_mode_auto_comment' => 'Ativada automaticamente mediante o cadastro.', + 'activate_mode_user' => 'Usuário', + 'activate_mode_user_comment' => 'O usuário ativa sua própria conta usando o email.', + 'activate_mode_admin' => 'Administrador', + 'activate_mode_admin_comment' => 'Apenas um Administrador pode ativar um usuário.', + 'require_activation' => 'Login requer ativação', + 'require_activation_comment' => 'Usuários precisam ter uma conta ativada para logar.', + 'use_throttle' => 'Tentativas limitadas', + 'use_throttle_comment' => 'Tentativas repetidas de login mal-sucedidas suspenderão temporariamente o usuário.', + 'login_attribute' => 'Atributo para login', + 'login_attribute_comment' => 'Selecione qual atributo do usuário deve ser usado para logar.', + ], + 'user' => [ + 'label' => 'Usuário', + 'id' => 'ID', + 'username' => 'Nome de usuário', + 'name' => 'Nome', + 'name_empty' => 'Anônimo', + 'surname' => 'Sobrenome', + 'email' => 'Email', + 'created_at' => 'Registrado', + 'last_seen' => 'Visto pela última vez', + 'is_guest' => 'Convidado', + 'joined' => 'Ingressou', + 'is_online' => 'Online agora', + 'is_offline' => 'Affline agora', + 'send_invite' => 'Enviar convite por e-mail', + 'send_invite_comment' => 'Envia uma mensagem de boas-vindas contendo informações de login e senha.', + 'create_password' => 'Criar Senha', + 'create_password_comment' => 'Informe uma senha para login do usuário.', + 'reset_password' => 'Resetar senha', + 'reset_password_comment' => 'Para resetar a senha deste usuário, informe uma nova senha aqui.', + 'confirm_password' => 'Confirmação de Senha', + 'confirm_password_comment' => 'Informe a senha novamente para confirmá-la.', + 'groups' => 'Grupos', + 'empty_groups' => 'Não há grupos disponíveis.', + 'avatar' => 'Avatar', + 'details' => 'Detalhes', + 'account' => 'Conta', + 'block_mail' => 'Bloquear todos os envios de e-mail para este usuário.', + 'status_guest' => 'Convidado', + 'status_activated' => 'Ativado', + 'status_registered' => 'Registrado' + ], + 'group' => [ + 'label' => 'Grupo', + 'id' => 'ID', + 'name' => 'Nome', + 'description_field' => 'Descrição', + 'code' => 'Código', + 'code_comment' => 'Insira um código exclusivo usado para identificar esse grupo.', + 'created_at' => 'Criado', + 'users_count' => 'Usuários' + ], + 'groups' => [ + 'menu_label' => 'Grupos', + 'all_groups' => 'Grupos de Usuários', + 'new_group' => 'Novo grupo', + 'delete_selected_confirm' => 'Deseja realmente excluir grupos selecionados?', + 'list_title' => 'Gerenciar grupos', + 'delete_confirm' => 'Deseja realmente excluir este grupo?', + 'delete_selected_success' => 'Os grupos selecionados foram excluídos com êxito.', + 'delete_selected_empty' => 'Não há grupos selecionados para excluir.', + 'return_to_list' => 'Voltar à lista de grupos', + 'return_to_users' => 'Voltar à lista de usuários', + 'create_title' => 'Criar grupo de Usuários', + 'update_title' => 'Editar grupo de usuários', + 'preview_title' => 'Visualização de grupo de usuário' + ], + 'login' => [ + 'attribute_email' => 'Email', + 'attribute_username' => 'Nome de usuário' + ], + 'account' => [ + 'account' => 'Conta', + 'account_desc' => 'Formulário de gerenciamento de usuário.', + 'redirect_to' => 'Redirecionar para', + 'redirect_to_desc' => 'Nome da página para a qual redirecionar após atualização, login ou cadastro.', + 'code_param' => 'Parâmetro de Código de Ativação', + 'code_param_desc' => 'O parâmetro de URL da página usado para o código de ativação de cadastro', + 'invalid_user' => 'Não foi encontrado um usuário com as credenciais informadas.', + 'invalid_activation_code' => 'Código de ativação informado inválido', + 'invalid_deactivation_pass' => 'A senha inserida é inválida.', + 'success_activation' => 'Sua conta foi ativada com sucesso.', + 'success_deactivation' => 'Sua conta foi desativada com sucesso. Lamentamos ver você ir!', + 'success_saved' => 'Configurações salvas com sucesso!', + 'login_first' => 'Você precisa logar primeiro!', + 'already_active' => 'Sua conta já está ativada!', + 'activation_email_sent' => 'Email de ativação foi enviado para o endereço de e-mail informado.', + 'registration_disabled' => 'Atualmente, as inscrições estão desabilitadas.', + 'sign_in' => 'Entrar', + 'register' => 'Cadastrar-se', + 'full_name' => 'Nome Completo', + 'email' => 'Email', + 'password' => 'Senha', + 'login' => 'Entrar', + 'new_password' => 'Nova Senha', + 'new_password_confirm' => 'Confirmar Nova Senha' + ], + 'reset_password' => [ + 'reset_password' => 'Resetar Senha', + 'reset_password_desc' => 'Formulário de resetar senha.', + 'code_param' => 'Parâmetro de código para resetar senha ', + 'code_param_desc' => 'O parâmetro de URL da página usado para o código' + ], + 'session' => [ + 'session' => 'Sessão', + 'session_desc' => 'Adiciona a sessão do usuário a uma página e pode restringir o acesso à página.', + 'security_title' => 'Permitir apenas', + 'security_desc' => 'Quem tem permissão para acessar esta página.', + 'all' => 'Todos', + 'users' => 'Usuários', + 'guests' => 'Convidados', + 'redirect_title' => 'Redirecionar para', + 'redirect_desc' => 'Nome da página para qual redirecionar se o acesso for negado.', + 'logout' => 'Você foi desconectado com sucesso!' + ] +]; diff --git a/plugins/rainlab/user/lang/pt-pt/lang.php b/plugins/rainlab/user/lang/pt-pt/lang.php new file mode 100644 index 0000000..cf2409c --- /dev/null +++ b/plugins/rainlab/user/lang/pt-pt/lang.php @@ -0,0 +1,189 @@ + [ + 'name' => 'Utilizador', + 'description' => 'Gestão de utilizadores de front-end.', + 'tab' => 'Utilizador', + 'access_users' => 'Gerir utilizadores', + 'access_groups' => 'Gerir grupos de utilizadores', + 'access_settings' => 'Gerir definições de utilizador' + ], + 'users' => [ + 'menu_label' => 'Utilizadores', + 'all_users' => 'Todos os utilizadores', + 'new_user' => 'Novo Utilizador', + 'list_title' => 'Gerir utilizadores', + 'trashed_hint_title' => 'O utilizador desactivou esta conta.', + 'trashed_hint_desc' => 'O utilizador desactivou esta conta e não pretende aceder ao site. O mesmo pode restaurar a conta em qualquer altura fazendo novamente a entrada.', + 'banned_hint_title' => 'O utilizador foi banido.', + 'banned_hint_desc' => 'Este utilizador foi banido por um administrador e não conseguirá fazer a entrada.', + 'guest_hint_title' => 'Utilizador convidado.', + 'guest_hint_desc' => 'Utilizador guardado para fins de referência e apenas precisa fazer registo antes de poder entrar.', + 'activate_warning_title' => 'Utilizador não activado!', + 'activate_warning_desc' => 'Este utilizador não foi activado e estará impossibilitado de entrar.', + 'activate_confirm' => 'Deseja ativar este utilizador?', + 'activated_success' => 'O Utilizador foi ativado com sucesso!', + 'activate_manually' => 'Activar este utilizador manualmente', + 'convert_guest_confirm' => 'Converter este convidado para utilizador?', + 'convert_guest_manually' => 'Converter para utilizador registado.', + 'convert_guest_success' => 'O utilizador foi convertido para uma conta registada', + 'delete_confirm' => 'Deseja eliminar este utilizador?', + 'unban_user' => 'Remover banimento a este utilizador', + 'unban_confirm' => 'Pretende remover banimento a este utilizador?', + 'unbanned_success' => 'Foi removido banimento deste utilizador', + 'return_to_list' => 'Regressar à lista de Utilizadores', + 'update_details' => 'Actualizar detalhes', + 'bulk_actions' => 'Acções em bloco', + 'delete_selected' => 'Eliminar seleccionados', + 'delete_selected_confirm' => 'Eliminar os utilizadores selecionados?', + 'delete_selected_empty' => 'Não há utilizadores selecionados para eliminar.', + 'delete_selected_success' => 'Utilizadores selecionados eliminados com sucesso.', + 'deactivate_selected' => 'Inactivar utilizadores seleccionados', + 'deactivate_selected_confirm' => 'Inactivar utilizadores seleccionados?', + 'deactivate_selected_empty' => 'Não existem utilizadores seleccionados para inactivar.', + 'deactivate_selected_success' => 'Utilizadores seleccionados inactivados com sucesso.', + 'restore_selected' => 'Restaurar utilizadores seleccionados', + 'restore_selected_confirm' => 'Restaurar utilizadores seleccionados?', + 'restore_selected_empty' => 'Não existem utilizadores seleccionados para restaurar.', + 'restore_selected_success' => 'Utilizadores seleccionados restaurados com sucesso.', + 'ban_selected' => 'Banir utilizadores seleccionados', + 'ban_selected_confirm' => 'Banir utilizadores seleccionados?', + 'ban_selected_empty' => 'Não existem utilizadores seleccionados para banir.', + 'ban_selected_success' => 'Utilizadores seleccionados banidos com sucesso.', + 'unban_selected' => 'Remover banimento a utilizadores seleccionados', + 'unban_selected_confirm' => 'Remover banimento a utilizadores seleccionados?', + 'unban_selected_empty' => 'Não existem utilizadores seleccionados para remover banimento.', + 'unban_selected_success' => 'Removido banimento com sucesso aos utilizadores seleccionados.', + ], + 'settings' => [ + 'users' => 'Utilizadores', + 'menu_label' => 'Configurações de Utilizador', + 'menu_description' => 'Gerir configurações relacionadas a Utilizadores.', + 'activation_tab' => 'Activação', + 'signin_tab' => 'Entrar', + 'registration_tab' => 'Registo', + 'notifications_tab' => 'Notificatções', + 'allow_registration' => 'Permitir registo de utilizador', + 'allow_registration_comment' => 'Se inactivo os utilizadores só poderão ser criados por administradores.', + 'activate_mode' => 'Modo de activação', + 'activate_mode_comment' => 'Selecione como uma conta de utilizador deve ser activada.', + 'activate_mode_auto' => 'Automático', + 'activate_mode_auto_comment' => 'Activada automaticamente mediante o registo.', + 'activate_mode_user' => 'Utilizador', + 'activate_mode_user_comment' => 'O utilizador activa a própria conta usando o e-mail.', + 'activate_mode_admin' => 'Administrador', + 'activate_mode_admin_comment' => 'Apenas um Administrador pode activar um utilizador.', + 'require_activation' => 'Permissão para entrar requer ativação', + 'require_activation_comment' => 'Utilizadores precisam ter uma conta activada para entrar.', + 'use_throttle' => 'Tentativas limitadas', + 'use_throttle_comment' => 'Tentativas repetidas de entrada mal-sucedidas suspenderão temporariamente o utilizador.', + 'login_attribute' => 'Atributo para entrar', + 'login_attribute_comment' => 'Selecione qual atributo do utilizador deve ser usado para entrar.', + ], + 'user' => [ + 'label' => 'Utilizador', + 'id' => 'ID', + 'username' => 'Nome de utilizador', + 'name' => 'Nome', + 'name_empty' => 'Anonymous', + 'surname' => 'Último nome', + 'email' => 'E-mail', + 'created_at' => 'Registado em', + 'last_seen' => 'Visto por último', + 'is_guest' => 'Convidado', + 'joined' => 'Registou-se a', + 'is_online' => 'Online agora', + 'is_offline' => 'Desligado', + 'send_invite' => 'E-mail de convite enviado', + 'send_invite_comment' => 'Emvia uma mensagem de Boas Vindas contendo informações de acesso.', + 'create_password' => 'Criar password', + 'create_password_comment' => 'Informe uma password para entrada do utilizador.', + 'reset_password' => 'Redefinir password', + 'reset_password_comment' => 'Para redefinir a password deste utilizador, informe uma nova password aqui.', + 'confirm_password' => 'Confirmação de password', + 'confirm_password_comment' => 'Informe a password novamente para confirmá-la.', + 'groups' => 'Grupos', + 'empty_groups' => 'Não há grupos disponíveis.', + 'avatar' => 'Avatar', + 'details' => 'Detalhes', + 'account' => 'Conta', + 'block_mail' => 'Bloquear todos os envios de e-mail para este Utilizador.', + 'status_guest' => 'Convidado', + 'status_activated' => 'Activado', + 'status_registered' => 'Registado', + ], + 'group' => [ + 'label' => 'Grupo', + 'id' => 'ID', + 'name' => 'Nome', + 'description_field' => 'Descrição', + 'code' => 'Código', + 'code_comment' => 'Introduza um código único para identificar este grupo.', + 'created_at' => 'Criado', + 'users_count' => 'Utilizadores' + ], + 'groups' => [ + 'menu_label' => 'Grupos', + 'all_groups' => 'Grupos de utilizador', + 'new_group' => 'Novo grupo', + 'delete_selected_confirm' => 'Pretende eliminar os grupos seleccionados?', + 'list_title' => 'Gerir grupos', + 'delete_confirm' => 'Pretende eliminar este grupo?', + 'delete_selected_success' => 'Grupos seleccionados eliminados com sucesso.', + 'delete_selected_empty' => 'Não existem grupos seleccionados para elimianr.', + 'return_to_list' => 'Regressar à lista de grupos', + 'return_to_users' => 'Regressar à lista de utilizadores', + 'create_title' => 'Criar Grupo de utilizadores', + 'update_title' => 'Editar grupo de utilizadores', + 'preview_title' => 'Previsão de grupo de utilizadores' + ], + 'login' => [ + 'attribute_email' => 'E-mail', + 'attribute_username' => 'Nome de utilizador' + ], + 'account' => [ + 'account' => 'Conta', + 'account_desc' => 'Formulário de gerenciamento de utilizador.', + 'redirect_to' => 'Redirecionar para', + 'redirect_to_desc' => 'Nome da página para a qual redirecionar após atualização, entrada ou registo.', + 'code_param' => 'Parâmetro de Código de Ativação', + 'code_param_desc' => 'O parâmetro de URL da página usado para o código de ativação de registo', + 'invalid_user' => 'Não foi encontrado um utilizador com as credenciais informadas.', + 'invalid_activation_code' => 'Código de ativação inserido é inválido', + 'invalid_deactivation_pass' => 'A password inserida é inválida.', + 'success_activation' => 'Conta foi ativada com sucesso.', + 'success_deactivation' => 'A conta foi inactivada com sucesso. Lamentamos vê-lo ir-se embora!', + 'success_saved' => 'Configurações guardadas com sucesso!', + 'login_first' => 'Precisa efectuar a entrada primeiro!', + 'already_active' => 'A sua conta já está ativada!', + 'activation_email_sent' => 'E-mail de activação foi enviado para o endereço de e-mail fornecido.', + 'registration_disabled' => 'Registrations are currently disabled.', + 'sign_in' => 'Entrar', + 'register' => 'Fazer registo', + 'full_name' => 'Nome Completo', + 'email' => 'E-mail', + 'password' => 'Password', + 'login' => 'Entrar', + 'new_password' => 'Nova Password', + 'new_password_confirm' => 'Confirmar nova password' + ], + 'reset_password' => [ + 'reset_password' => 'Redefinir password', + 'reset_password_desc' => 'Formulário de redefinição de password .', + 'code_param' => 'Parâmetro de código para redefinir password ', + 'code_param_desc' => 'O parâmetro de URL da página usado para o código' + ], + 'session' => [ + 'session' => 'Sessão', + 'session_desc' => 'Adiciona a sessão do utilizador a uma página e pode restringir o acesso à página.', + 'security_title' => 'Permitir apenas', + 'security_desc' => 'Quem tem permissão para aceder a esta página.', + 'all' => 'Todos', + 'users' => 'Utilizadores', + 'guests' => 'Visitantes', + 'redirect_title' => 'Redirecionar para', + 'redirect_desc' => 'Nome da página para qual redirecionar se o acesso for negado.', + 'logout' => 'A sessão foi terminada com sucesso!' + ] +]; diff --git a/plugins/rainlab/user/lang/ru/lang.php b/plugins/rainlab/user/lang/ru/lang.php new file mode 100644 index 0000000..90ca841 --- /dev/null +++ b/plugins/rainlab/user/lang/ru/lang.php @@ -0,0 +1,224 @@ + [ + 'name' => 'Пользователи', + 'description' => 'Фронтенд управление пользователÑми.', + 'tab' => 'Пользователи', + 'access_users' => 'Управление пользователÑми', + 'access_groups' => 'Управление группами пользователей', + 'access_settings' => 'Управление наÑтройками пользователей', + 'impersonate_user' => 'Войти как Ñтот пользователь', + ], + 'users' => [ + 'menu_label' => 'Пользователи', + 'all_users' => 'Ð’Ñе пользователи', + 'new_user' => 'Ðовый пользователь', + 'list_title' => 'Управление пользователÑми', + 'trashed_hint_title' => 'Пользователь деактивировал Ñвой аккаунт', + 'trashed_hint_desc' => 'Этот пользователь деактивировал Ñвой аккаунт. Он может реактивировать Ñвой аккаунт в любое времÑ.', + 'banned_hint_title' => 'Пользователь заблокирован', + 'banned_hint_desc' => 'Этот пользователь заблокирован админиÑтратором и не Ñможет авторизоватьÑÑ.', + 'guest_hint_title' => 'Это гоÑÑ‚ÐµÐ²Ð°Ñ ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ', + 'guest_hint_desc' => 'Этот пользователь Ñохранен только Ð´Ð»Ñ Ñправочных целей и должен быть зарегиÑтрирован, прежде чем Ñможет выполнить вход.', + 'activate_warning_title' => 'Пользователь не активирован!', + 'activate_warning_desc' => 'Этот пользователь не активирован и не Ñможет войти.', + 'activate_confirm' => 'Ð’Ñ‹ дейÑтвительно хотите активировать данного пользователÑ?', + 'activated_success' => 'Пользователь был уÑпешно активирован!', + 'activate_manually' => 'Ðктивировать Ñтого Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð²Ñ€ÑƒÑ‡Ð½ÑƒÑŽ', + 'convert_guest_confirm' => 'Преобразовать гоÑÑ‚Ñ Ð² пользователÑ?', + 'convert_guest_manually' => 'Преобразовать в зарегиÑтрированного пользователÑ', + 'convert_guest_success' => 'ГоÑÑ‚ÐµÐ²Ð°Ñ ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ преобразована в зарегиÑтрированную.', + 'impersonate_user' => 'Войти как Ñтот пользователь', + 'impersonate_confirm' => 'Войти как Ñтот пользователь? Ð’Ñ‹ Ñможете вернутьÑÑ Ð² иÑходное ÑоÑтоÑние поÑле разлогиниваниÑ.', + 'impersonate_success' => 'Ð’Ñ‹ теперь предÑтавлены как другой пользователь', + 'delete_confirm' => 'Ð’Ñ‹ дейÑтвительно хотите удалить Ñтого пользователÑ?', + 'unban_user' => 'Разблокировать', + 'unban_confirm' => 'Ð’Ñ‹ уверены, что хотите разблокировать Ñтого пользователÑ?', + 'unbanned_success' => 'Пользователь разблокирован', + 'return_to_list' => 'ВернутьÑÑ Ðº ÑпиÑку пользователей', + 'update_details' => 'Изменить данные', + 'bulk_actions' => 'МаÑÑовые дейÑтвиÑ', + 'delete_selected' => 'Удалить выбранные', + 'delete_selected_confirm' => 'Удалить выбранных пользователей?', + 'delete_selected_empty' => 'Ðет выбранных пользователей Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ.', + 'delete_selected_success' => 'Выбранные пользователи уÑпешно удалены.', + 'activate_selected' => 'Ðктивировать выбранные', + 'activate_selected_confirm' => 'Ðктивировать выбранных пользователей?', + 'activate_selected_empty' => 'Ðет выбранных пользователей Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ð¸.', + 'activate_selected_success' => 'Выбранные пользователи уÑпешно активированы.', + 'deactivate_selected' => 'Деактивировать выбранные', + 'deactivate_selected_confirm' => 'Деактивировать выбранных пользователей?', + 'deactivate_selected_empty' => 'Ðет выбранных пользователей Ð´Ð»Ñ Ð´ÐµÐ°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ð¸.', + 'deactivate_selected_success' => 'Выбранные пользователи уÑпешно деактивированы.', + 'restore_selected' => 'ВоÑÑтановить выбранные', + 'restore_selected_confirm' => 'ВоÑÑтановить выбранных пользователей?', + 'restore_selected_empty' => 'Ðет выбранных пользователей Ð´Ð»Ñ Ð²Ð¾ÑÑтановлениÑ.', + 'restore_selected_success' => 'Выбранные пользователи уÑпешно воÑÑтановлены.', + 'ban_selected' => 'Заблокировать выбранные', + 'ban_selected_confirm' => 'Заблокировать выбранных пользователей?', + 'ban_selected_empty' => 'Ðет выбранных пользователей Ð´Ð»Ñ Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ¸.', + 'ban_selected_success' => 'Выбранные пользователи уÑпешно заблокированы.', + 'unban_selected' => 'Разблокировать выбранные', + 'unban_selected_confirm' => 'Разблокировать выбранных пользователей?', + 'unban_selected_empty' => 'Ðет выбранных пользователей Ð´Ð»Ñ Ñ€Ð°Ð·Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ¸.', + 'unban_selected_success' => 'Выбранные пользователи уÑпешно разблокированы.', + 'unsuspend' => 'ПриоÑтановлен', + 'unsuspend_success' => 'Пользователь был приоÑтановлен.', + 'unsuspend_confirm' => 'ПриоÑтановить данного пользователÑ?' + ], + 'settings' => [ + 'users' => 'Пользователи', + 'menu_label' => 'ÐаÑтройки пользователÑ', + 'menu_description' => 'Ð£Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð°Ð¼Ð¸ пользователÑ.', + 'activation_tab' => 'ÐктивациÑ', + 'signin_tab' => 'ÐвторизациÑ', + 'registration_tab' => 'РегиÑтрациÑ', + 'profile_tab' => 'Профиль', + 'notifications_tab' => 'ОповещениÑ', + 'allow_registration' => 'Разрешить региÑтрацию', + 'allow_registration_comment' => 'ЕÑли Ñта Ð¾Ð¿Ñ†Ð¸Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°, только админиÑтраторы Ñмогут региÑтрировать пользователей.', + 'activate_mode' => 'ÐктивациÑ', + 'activate_mode_comment' => 'ÐÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ.', + 'activate_mode_auto' => 'ÐвтоматичеÑкаÑ', + 'activate_mode_auto_comment' => 'ÐвтоматичеÑÐºÐ°Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸ региÑтрации.', + 'activate_mode_user' => 'СтандартнаÑ', + 'activate_mode_user_comment' => 'ÐÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸ помощи Ñлектронной почты.', + 'activate_mode_admin' => 'РучнаÑ', + 'activate_mode_admin_comment' => 'Только админиÑтратор может активировать пользователÑ.', + 'require_activation' => 'ОбÑÐ·Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð°ÐºÐºÐ°ÑƒÐ½Ñ‚Ð°', + 'require_activation_comment' => 'Пользователи должны иметь активированный аккаунт Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð°.', + 'use_throttle' => 'ОтÑлеживание неудачных попыток авторизации', + 'use_throttle_comment' => 'При множеÑтвенных неудачных попытках авторизации пользователь будет заморожен.', + 'use_register_throttle' => 'ПриоÑтанавливать региÑтрацию', + 'use_register_throttle_comment' => 'Предотвращение большого количеÑтва региÑтраций Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ IP-адреÑа в короткий Ñрок.', + 'block_persistence' => 'Запретить параллельные ÑеÑÑии', + 'block_persistence_comment' => 'ЕÑли включено, пользователи не могут войти Ñ Ñ€Ð°Ð·Ð½Ñ‹Ñ… уÑтройÑтв одновременно.', + 'login_attribute' => 'Логин', + 'login_attribute_comment' => 'Поле, иÑпользуемое в качеÑтве логина пользователÑ.', + 'remember_login' => 'Режим "Запомнить менÑ"', + 'remember_login_comment' => 'Выберите, должна ли ÑеÑÑÐ¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð±Ñ‹Ñ‚ÑŒ поÑтоÑнной.', + 'remember_always' => 'Ð’Ñегда', + 'remember_never' => 'Ðикогда', + 'remember_ask' => 'СпроÑить Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¿Ñ€Ð¸ входе', + ], + 'user' => [ + 'label' => 'Пользователь', + 'id' => 'ID', + 'username' => 'Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ', + 'name' => 'ИмÑ', + 'name_empty' => 'Ðноним', + 'surname' => 'ФамилиÑ', + 'email' => 'Email', + 'created_at' => 'Дата региÑтрации', + 'last_seen' => 'ПоÑледнÑÑ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾Ñть', + 'is_guest' => 'ГоÑть', + 'joined' => 'ЗарегиÑтрирован', + 'is_online' => 'Ð’ Ñети', + 'is_offline' => 'Ðе в Ñети', + 'send_invite' => 'Отправить приглашение по почте', + 'send_invite_comment' => 'ОтправлÑет приветÑтвеннное Ñообщение на почту Ñ Ð»Ð¾Ð³Ð¸Ð½Ð¾Ð¼ и паролем Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ð°.', + 'create_password' => 'Создать пароль', + 'create_password_comment' => 'Введите новый пароль Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ.', + 'reset_password' => 'Ð¡Ð±Ñ€Ð¾Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ', + 'reset_password_comment' => 'Ð”Ð»Ñ ÑброÑа Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð²Ð²ÐµÐ´Ð¸Ñ‚Ðµ здеÑÑŒ новый пароль.', + 'confirm_password' => 'Подтверждение паролÑ', + 'confirm_password_comment' => 'Введите пароль еще раз Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ.', + 'groups' => 'Группы', + 'empty_groups' => 'Ðет групп, доÑтупных пользователю.', + 'avatar' => 'Ðватар', + 'details' => 'ИнформациÑ', + 'account' => 'Ðккаунт', + 'block_mail' => 'Отключить вÑÑŽ иÑходÑщую почту Ð´Ð»Ñ Ñтого пользователÑ.', + 'status_label' => 'СтатуÑ', + 'status_guest' => 'ГоÑть', + 'status_activated' => 'Ðктивирован', + 'status_registered' => 'ЗарегиÑтрирован', + 'created_ip_address' => 'Создан Ñ IP-адреÑа', + 'last_ip_address' => 'ПоÑледний IP-адреÑ', + ], + 'group' => [ + 'label' => 'Группа', + 'id' => 'ID', + 'name' => 'ИмÑ', + 'description_field' => 'ОпиÑание', + 'code' => 'Код', + 'code_comment' => 'Введите уникальный код Ð´Ð»Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¸ Ñтой группы.', + 'created_at' => 'Дата ÑозданиÑ', + 'users_count' => 'Пользователей', + ], + 'groups' => [ + 'menu_label' => 'Группы', + 'all_groups' => 'Группы пользователей', + 'new_group' => 'ÐÐ¾Ð²Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð°', + 'delete_selected_confirm' => 'Ð’Ñ‹ дейÑтвительно хотите удалить выбранные группы?', + 'list_title' => 'Управление группами', + 'delete_confirm' => 'Ð’Ñ‹ дейÑтвительно хотите удалить Ñту группу?', + 'delete_selected_success' => 'Выбранные группы удалены.', + 'delete_selected_empty' => 'Ðе выбраны группы Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ.', + 'return_to_list' => 'ВернутÑÑ Ðº ÑпиÑку групп', + 'return_to_users' => 'ВернутÑÑ Ðº ÑпиÑку пользователей', + 'create_title' => 'Создание группы', + 'update_title' => 'Редактирование группы', + 'preview_title' => 'ПредпроÑмотр группы', + ], + 'login' => [ + 'attribute_email' => 'Email', + 'attribute_username' => 'Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ', + ], + 'account' => [ + 'account' => 'Ðккаунт', + 'account_desc' => 'Управление формой.', + 'banned' => 'Извините, Ñтот пользователь заблокирован. ОбратитеÑÑŒ к админиÑтратору за помощью.', + 'redirect_to' => 'Перенаправление', + 'redirect_to_desc' => 'Страница Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñле обновлениÑ, входа или региÑтрации.', + 'code_param' => 'Параметр кода', + 'code_param_desc' => 'Параметр, в котором передаётÑÑ ÐºÐ¾Ð´ активации.', + 'force_secure' => 'ИÑпользовать HTTPS', + 'force_secure_desc' => 'Ð’Ñегда перенаправлÑть через HTTPS.', + 'invalid_user' => 'Пользователь Ñ Ñ‚Ð°ÐºÐ¸Ð¼Ð¸ данным не найден.', + 'invalid_activation_code' => 'Ðеверный код активации.', + 'invalid_deactivation_pass' => 'Введенный Вами пароль некорректен.', + 'invalid_current_pass' => 'Текущий пароль который вы ввели - недейÑтвителен.', + 'success_activation' => 'УÑÐ¿ÐµÑˆÐ½Ð°Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ.', + 'success_deactivation' => 'Ваш аккаунт был деактивирован.', + 'success_saved' => 'ÐаÑтройки уÑпешно Ñохранены!', + 'login_first' => 'Вам необходимо войти под Ñвоими данными!', + 'already_active' => 'Ваш аккаунт ещё активирован!', + 'activation_email_sent' => 'ПиÑьмо Ñ Ð´Ð°Ð»ÑŒÐ½ÐµÐ¹ÑˆÐ¸Ð¼Ð¸ инÑтрукциÑми по активации было отправлено на указанный Ð°Ð´Ñ€ÐµÑ Ñлектронной почты.', + 'activation_by_admin' => 'Ð’Ñ‹ уÑпешно зарегиÑтрировалиÑÑŒ. Ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ пока еще не активна и должна быть одобрена админиÑтратором.', + 'registration_disabled' => 'РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ ÑÐµÐ¹Ñ‡Ð°Ñ Ð½ÐµÐ´Ð¾Ñтупна.', + 'registration_throttled' => 'РегиÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸Ð¾Ñтановлена. ПожалуйÑта, попробуйте позже.', + 'sign_in' => 'ÐвторизациÑ', + 'register' => 'РегиÑтрациÑ', + 'full_name' => 'Полное имÑ', + 'email' => 'Email', + 'password' => 'Пароль', + 'login' => 'Логин', + 'new_password' => 'Ðовый пароль', + 'new_password_confirm' => 'Подтверждение паролÑ', + 'update_requires_password' => 'Подтверждать пароль при обновлении', + 'update_requires_password_comment' => 'Запрашивать текущий пароль Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¿Ñ€Ð¸ редактировании его профилÑ.', + ], + 'reset_password' => [ + 'reset_password' => 'Ð¡Ð±Ñ€Ð¾Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ', + 'reset_password_desc' => 'Форма воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ.', + 'code_param' => 'Параметр кода', + 'code_param_desc' => 'Параметр, в котором передаётÑÑ ÐºÐ¾Ð´ ÑброÑа паролÑ.', + ], + 'session' => [ + 'session' => 'СеÑÑиÑ', + 'session_desc' => 'Добавление пользовательÑкого ÑеанÑа к Ñтранице (доÑтуп)', + 'security_title' => 'ДоÑтуп к Ñтранице', + 'security_desc' => 'Кто имеет право на доÑтуп к Ñтой Ñтранице.', + 'all' => 'Ð’Ñе', + 'users' => 'Пользователи', + 'guests' => 'ГоÑти', + 'allowed_groups_title' => 'Разрешённые группы', + 'allowed_groups_description' => 'Выберите разрешённые группы или ничего, чтобы разрешить вÑе', + 'redirect_title' => 'Перенаправление', + 'redirect_desc' => 'Страница Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ отÑутÑтвии доÑтупа.', + 'logout' => 'Ð’Ñ‹ уÑпешно вышли из ÑиÑтемы!', + 'stop_impersonate_success' => 'Ð’Ñ‹ больше не предÑтавлены как другой пользователь.', + ], +]; diff --git a/plugins/rainlab/user/lang/sk/lang.php b/plugins/rainlab/user/lang/sk/lang.php new file mode 100644 index 0000000..3056aef --- /dev/null +++ b/plugins/rainlab/user/lang/sk/lang.php @@ -0,0 +1,204 @@ + [ + 'name' => 'Požívateľ', + 'description' => 'Správa front-end používateľov.', + 'tab' => 'Požívatelia', + 'access_users' => 'Správa používateľov', + 'access_groups' => 'Správa skupín používateľov', + 'access_settings' => 'Správa používateľských nastavení', + 'impersonate_user' => 'ZosobniÅ¥ používateľov' + ], + 'users' => [ + 'menu_label' => 'Používatelia', + 'all_users' => 'VÅ¡etci používatelia', + 'new_user' => 'Nový používateľ', + 'list_title' => 'Správa používateľov', + 'trashed_hint_title' => 'Používateľ deaktivoval svoj úÄet', + 'trashed_hint_desc' => 'Tento používateľ deaktivoval svoj úÄet a už nechce byÅ¥ zobrazovaný na webe. Môže kedykoľvek obnoviÅ¥ svoj úÄet, keÄ sa prihlási späť.', + 'banned_hint_title' => 'Používateľ bol zakázaný', + 'banned_hint_desc' => 'Tento pouužívateľ bol zakázaný administrátorom a nebude sa môcÅ¥ prihlásiÅ¥.', + 'guest_hint_title' => 'Toto je hosÅ¥ujúci používateľ', + 'guest_hint_desc' => 'Tento používateľ je uložený iba na úÄely odkazovania a musí sa zaregistrovaÅ¥ pred prihlásením.', + 'activate_warning_title' => 'Používateľ nie je aktivovaný!', + 'activate_warning_desc' => 'Tento používateľ nebol aktivovaný a nemusí byÅ¥ schopný sa prihlásiÅ¥.', + 'activate_confirm' => 'Naozaj chcete aktivovaÅ¥ tohto používateľa?', + 'activated_success' => 'Používateľ bol aktivovaný', + 'activate_manually' => 'AktivovaÅ¥ tohto používateľa manuálne', + 'convert_guest_confirm' => 'KonvertovaÅ¥ tohto hosÅ¥a na používateľa?', + 'convert_guest_manually' => 'KonvertovaÅ¥ na registrovaného používateľa', + 'convert_guest_success' => 'Používateľ bol prevedený na zaregistrovaný úÄet', + 'impersonate_user' => 'ZosobniÅ¥ používateľa', + 'impersonate_confirm' => 'ZosobniÅ¥ toto používateľa? Môžete sa vrátiÅ¥ do pôvodného stavu odhlásením.', + 'impersonate_success' => 'Teraz zosobňujete tohoto používateľa', + 'delete_confirm' => 'Naozaj chcete zmazaÅ¥ tohto používateľa?', + 'unban_user' => 'ZruÅ¡iÅ¥ zákaz tohto používateľa', + 'unban_confirm' => 'Naozaj chcete zruÅ¡iÅ¥ zákaz tohto používateľa?', + 'unbanned_success' => 'Zákaz používateľa bol zruÅ¡ený', + 'return_to_list' => 'VrátiÅ¥ sa na zoznam používateľov', + 'update_details' => 'Aktualizujte detaily', + 'bulk_actions' => 'Hromadné akcie', + 'delete_selected' => 'ZmazaÅ¥ oznaÄené', + 'delete_selected_confirm' => 'ZmazaÅ¥ vybraných používateľov?', + 'delete_selected_empty' => 'Nie sú vybraní žiadni používatelia na odstránenie.', + 'delete_selected_success' => 'ÚspeÅ¡ne ste odstránili vybraných používateľov.', + 'activate_selected' => 'AktivovaÅ¥ vybraných', + 'activate_selected_confirm' => 'AktivovaÅ¥ vybraných používateľov?', + 'activate_selected_empty' => 'Nie sú vybraní žiadni používatelia na aktiváciu.', + 'activate_selected_success' => 'Vybraní používatelia boli úspeÅ¡ne aktivovaní.', + 'deactivate_selected' => 'DeaktivovaÅ¥ vybraných', + 'deactivate_selected_confirm' => 'DeaktivovaÅ¥ vybraných používateľov?', + 'deactivate_selected_empty' => 'Nie sú vybraní žiadni používatelia na deaktiváciu.', + 'deactivate_selected_success' => 'Vybraní používatelia boli úspeÅ¡ne deaktivovaní.', + 'restore_selected' => 'ObnoviÅ¥ vybraných', + 'restore_selected_confirm' => 'ObnoviÅ¥ vybraných používateľov?', + 'restore_selected_empty' => 'Nie sú vybraní žiadni používatelia na obnovenie.', + 'restore_selected_success' => 'Vybraní používatelia boli úspeÅ¡ne obnovení.', + 'ban_selected' => 'ZakázaÅ¥ vybraných', + 'ban_selected_confirm' => 'ZakázaÅ¥ vybraných používateľov?', + 'ban_selected_empty' => 'Nie sú vybraní žiadni používatelia na zakázanie.', + 'ban_selected_success' => 'Vybraní používatelia boli úspeÅ¡ne zakázaní.', + 'unban_selected' => 'ZruÅ¡iÅ¥ zákaz vybraných', + 'unban_selected_confirm' => 'ZruÅ¡iÅ¥ zakáz vybraných používateľov?', + 'unban_selected_empty' => 'Nie sú vybraní žiadni používatelia na zruÅ¡enie zakázu.', + 'unban_selected_success' => 'Vybraným používateľom bol úspeÅ¡ne zruÅ¡ený zakáz.', + ], + 'settings' => [ + 'users' => 'Používatelia', + 'menu_label' => 'Nastavenie používateľov', + 'menu_description' => 'Správa nastavení používateľov.', + 'activation_tab' => 'Aktivácia', + 'signin_tab' => 'Prihlásenie', + 'registration_tab' => 'Registrácia', + 'notifications_tab' => 'Notifikácie', + 'allow_registration' => 'PovoliÅ¥ registráciu používateľa', + 'allow_registration_comment' => 'Ak je to zakázané, použávatelia môžu byÅ¥ vytvorený iba administrátormi.', + 'activate_mode' => 'Režim aktivácie', + 'activate_mode_comment' => 'Vyberte spôsob aktivácie používateľského úÄtu.', + 'activate_mode_auto' => 'Automatický', + 'activate_mode_auto_comment' => 'Automaticky sa aktivuje pri registrácii.', + 'activate_mode_user' => 'Používateľ', + 'activate_mode_user_comment' => 'Používateľ aktivuje svoj vlastný úÄet emailom.', + 'activate_mode_admin' => 'Administrátor', + 'activate_mode_admin_comment' => 'Iba Administrátor môže aktivovaÅ¥ používateľa.', + 'require_activation' => 'Prihlásenie vyžaduje aktiváciu', + 'require_activation_comment' => 'Používatelia musia maÅ¥ aktivovaný úÄet na prihlásenie.', + 'use_throttle' => 'ObmedziÅ¥ pokusy', + 'use_throttle_comment' => 'Opakované neúspeÅ¡né pokusy o prihlásenie používateľov doÄasne zablokuje.', + 'block_persistence' => 'ZabrániÅ¥ súbežným reláciám', + 'block_persistence_comment' => 'Po zapnutí sa používatelia nemôžu prihlásiÅ¥ do viacerých zariadení súÄasne.', + 'login_attribute' => 'Prihlasovací atribút', + 'login_attribute_comment' => 'Vyberte, aké základný údaj používateľa sa má použiÅ¥ pri prihlasovaní.', + ], + 'user' => [ + 'label' => 'Používateľ', + 'id' => 'ID', + 'username' => 'Užívateľské meno', + 'name' => 'Meno', + 'name_empty' => 'Anonym', + 'surname' => 'Priezvisko', + 'email' => 'E-mail', + 'created_at' => 'Registrovaný', + 'last_seen' => 'Naposledy videný', + 'is_guest' => 'HosÅ¥', + 'joined' => 'Pridaný', + 'is_online' => 'Teraz online', + 'is_offline' => 'Momentálne je offline', + 'send_invite' => 'PoslaÅ¥ pozvánku e-mailom', + 'send_invite_comment' => 'OdoÅ¡le uvítaciu správu obsahujúcu informácie o prihlásení a hesle.', + 'create_password' => 'VytvoriÅ¥ heslo', + 'create_password_comment' => 'Zadajte nové heslo, ktoré sa používa na prihlásenie.', + 'reset_password' => 'ObnoviÅ¥ heslo', + 'reset_password_comment' => 'Ak chcete obnoviÅ¥ heslo používateľa, zadajte nové heslo tu.', + 'confirm_password' => 'Potvrdenie hesla', + 'confirm_password_comment' => 'Znova zadajte heslo a potvrÄte ho.', + 'groups' => 'Skupiny', + 'empty_groups' => 'Neexistujú žiadne skupiny používateľov.', + 'avatar' => 'Avatar', + 'details' => 'Detaily', + 'account' => '=ÚÄet', + 'block_mail' => 'Zablokujte vÅ¡etku odchádzajúcu poÅ¡tu odoslanú tomuto používateľovi.', + 'status_guest' => 'HosÅ¥', + 'status_activated' => 'Aktivovaný', + 'status_registered' => 'Registrovaný', + ], + 'group' => [ + 'label' => 'Skupina', + 'id' => 'ID', + 'name' => 'Meno', + 'description_field' => 'Popis', + 'code' => 'Kód', + 'code_comment' => 'Zadajte jedineÄný kód použitý na identifikáciu tejto skupiny.', + 'created_at' => 'Vytvorená', + 'users_count' => 'Používatelia' + ], + 'groups' => [ + 'menu_label' => 'Skupiny', + 'all_groups' => 'Skupiny používateľov', + 'new_group' => 'Nová skupina', + 'delete_selected_confirm' => 'Naozaj chcete odstrániÅ¥ vybrané skupiny?', + 'list_title' => 'Správa skupín', + 'delete_confirm' => 'Naozaj chcete odstrániÅ¥ túto skupinu?', + 'delete_selected_success' => 'Vybrané skupiny boli úspeÅ¡ne odstránené.', + 'delete_selected_empty' => 'Nie sú vybrané žiadne skupiny na odstránenie.', + 'return_to_list' => 'Späť na zoznam skupín', + 'return_to_users' => 'Späť na zoznam používateľov', + 'create_title' => 'VytvoriÅ¥ skupinu používateľov', + 'update_title' => 'UpraviÅ¥ skupinu používateľov', + 'preview_title' => 'Ukážka skupiny používateľov' + ], + 'login' => [ + 'attribute_email' => 'E-mail', + 'attribute_username' => 'Užívateľské meno' + ], + 'account' => [ + 'account' => 'ÚÄet', + 'account_desc' => 'Formulár správy používateľov.', + 'banned' => 'Ospravedlňujeme sa, tento používateľ momentálne nie je aktivovaný. Kontaktujte nás pre ÄalÅ¡iu pomoc.', + 'redirect_to' => 'PresmerovaÅ¥ na', + 'redirect_to_desc' => 'Názov stránky na presmerovanie po aktualizácii, prihlásení alebo registrácii.', + 'code_param' => 'AktivaÄný kód Parameter', + 'code_param_desc' => 'Parameter URL stránky použitý ako kód aktivácie registrácie', + 'force_secure' => 'VynútiÅ¥ bezpeÄný protokol', + 'force_secure_desc' => 'Vždy presmerujte adresu URL schémou HTTPS.', + 'invalid_user' => 'Používateľ s uvedenými povereniami nebol nájdený.', + 'invalid_activation_code' => 'Bol zadaný neplatný aktivaÄný kód.', + 'invalid_deactivation_pass' => 'Zadané heslo je neplatné.', + 'success_activation' => 'Váš úÄet bol úspeÅ¡ne aktivovaný.', + 'success_deactivation' => 'Váš úÄet bol úspeÅ¡ne deaktivovaný. Je nám ľúto, že vás odchádzate!', + 'success_saved' => 'Nastavenia boli úspeÅ¡ne uložené!', + 'login_first' => 'Najprv musíte byÅ¥ prihlásení!', + 'already_active' => 'Váš úÄet je už aktivovaný!', + 'activation_email_sent' => 'Na vaÅ¡u e-mailovú adresu bol odoslaný aktivaÄný e-mail.', + 'registration_disabled' => 'Registrácie sú momentálne nedostupné.', + 'sign_in' => 'PrihlásiÅ¥ sa', + 'register' => 'RegistrovaÅ¥', + 'full_name' => 'Celé meno', + 'email' => 'E-mail', + 'password' => 'Heslo', + 'login' => 'PrihlásiÅ¥ sa', + 'new_password' => 'Nové heslo', + 'new_password_confirm' => 'PotvrÄte nové heslo' + ], + 'reset_password' => [ + 'reset_password' => 'ObnoviÅ¥ heslo', + 'reset_password_desc' => 'Formulár pre zabudnuté heslo.', + 'code_param' => 'Obnovovací kód Parameter', + 'code_param_desc' => 'Parameter URL stránky použitý pre obnovovací kód' + ], + 'session' => [ + 'session' => 'Relácia', + 'session_desc' => 'Pridá reláciu používateľa na stránku a môže obmedziÅ¥ prístup na stránku.', + 'security_title' => 'PovoliÅ¥ iba', + 'security_desc' => 'Kto má prístup na túto stránku.', + 'all' => 'VÅ¡etci', + 'users' => 'Užívatelia', + 'guests' => 'Hostia', + 'allowed_groups_title' => 'PovoliÅ¥ skupiny', + 'allowed_groups_description' => 'Vyberte povolené skupiny alebo žiadne, aby ste povolili vÅ¡etky skupiny', + 'redirect_title' => 'PresmerovaÅ¥ na', + 'redirect_desc' => 'Názov stránky pre presmerovanie, ak je prístup zamietnutý.', + 'logout' => 'ÚspeÅ¡ne ste sa odhlásili!', + 'stop_impersonate_success' => 'Už sa nezosobňujete používateľa.', + ] +]; diff --git a/plugins/rainlab/user/lang/sl/lang.php b/plugins/rainlab/user/lang/sl/lang.php new file mode 100644 index 0000000..50ed53d --- /dev/null +++ b/plugins/rainlab/user/lang/sl/lang.php @@ -0,0 +1,222 @@ + [ + 'name' => 'Uporabniki', + 'description' => 'Upravljanje uporabnikov spletne strani.', + 'tab' => 'Uporabniki', + 'access_users' => 'Upravljanje uporabnikov', + 'access_groups' => 'Upravljanje uporabniÅ¡kih skupin', + 'access_settings' => 'Upravljanje uporabniÅ¡kih nastavitev', + 'impersonate_user' => 'Impersonacija uporabnikov', + ], + 'users' => [ + 'menu_label' => 'Uporabniki', + 'all_users' => 'Vsi uporabniki', + 'new_user' => 'Nov uporabnik', + 'list_title' => 'Upravljanje uporabnikov', + 'trashed_hint_title' => 'Uporabnik je deaktiviral svoj raÄun', + 'trashed_hint_desc' => 'Ta uporabnik je deaktiviral svoj raÄun in se ne želi veÄ pojavljati na spletni strani. Svoj raÄun lahko kadarkoli obnovi s prijavo.', + 'banned_hint_title' => 'Uporabnik je bil blokiran', + 'banned_hint_desc' => 'Tega uporabnika je administrator blokiral in se ne more veÄ prijaviti.', + 'guest_hint_title' => 'Ta uporabnik je gost', + 'guest_hint_desc' => 'Ta uporabnik je shranjen samo za referenÄne namene. ÄŒe se želi prijaviti, se mora najprej registrirati.', + 'activate_warning_title' => 'Uporabnik ni aktiven.', + 'activate_warning_desc' => 'Ta uporabnik ni bil aktiviran in se ne more prijaviti.', + 'activate_confirm' => 'Ali ste prepriÄani, da želite aktivirati tega uporabnika?', + 'activated_success' => 'Uporabnik je bil aktiviran.', + 'activate_manually' => 'RoÄno aktivirajte tega uporabnika', + 'convert_guest_confirm' => 'Želite gosta spremeniti v uporabnika?', + 'convert_guest_manually' => 'Spremeni v registriranega uporabnika', + 'convert_guest_success' => 'Uporabnik je bil spremenjen v registriranega uporabnika.', + 'impersonate_user' => 'Impersoniraj uporabnika', + 'impersonate_confirm' => 'Ali ste prepriÄani, da želite impersonirati tega uporabnika? V prvotno stanje se lahko vrnete tako, da se odjavite.', + 'impersonate_success' => 'Sedaj impersonirate tega uporabnika.', + 'delete_confirm' => 'Ali ste prepriÄani, da želite izbrisati tega uporabnika?', + 'unban_user' => 'Odblokiranje uporabnika', + 'unban_confirm' => 'Ali ste prepriÄani, da želite odblokirati tega uporabnika?', + 'unbanned_success' => 'Uporabnik je bil odblokiran.', + 'return_to_list' => 'Vrni se na seznam uporabnikov', + 'update_details' => 'Posodobite podrobnosti', + 'bulk_actions' => 'Skupna dejanja', + 'delete_selected' => 'IzbriÅ¡i izbrane', + 'delete_selected_confirm' => 'IzbriÅ¡em izbrane uporabnike?', + 'delete_selected_empty' => 'Ni izbranih uporabnikov za izbris.', + 'delete_selected_success' => 'Izbrani uporabniki so bili uspeÅ¡no izbrisani.', + 'activate_selected' => 'Aktiviraj izbrane', + 'activate_selected_confirm' => 'Aktiviram izbrane uporabnike?', + 'activate_selected_empty' => 'Ni izbranih uporabnikov za aktivacijo.', + 'activate_selected_success' => 'Izbrani uporabniki so bili uspeÅ¡no aktivirani.', + 'deactivate_selected' => 'Deaktiviraj izbrane', + 'deactivate_selected_confirm' => 'Deaktiviram izbrane uporabnike?', + 'deactivate_selected_empty' => 'Ni izbranih uporabnikov za deaktivacijo.', + 'deactivate_selected_success' => 'Izbrani uporabniki so bili uspeÅ¡no deaktivirani.', + 'restore_selected' => 'Obnovi izbrane', + 'restore_selected_confirm' => 'Obnovim izbrane uporabnike?', + 'restore_selected_empty' => 'Ni izbranih uporabnikov za obnovitev.', + 'restore_selected_success' => 'Izbrani uporabniki so bili uspeÅ¡no obnovljeni.', + 'ban_selected' => 'Blokiraj izbrane', + 'ban_selected_confirm' => 'Blokiram izbrane uporabnike?', + 'ban_selected_empty' => 'Ni izbranih uporabnikov za blokado.', + 'ban_selected_success' => 'Izbrani uporabniki so bili uspeÅ¡no blokirani.', + 'unban_selected' => 'Odblokiraj izbrane', + 'unban_selected_confirm' => 'Odblokiram izbrane uporabnike?', + 'unban_selected_empty' => 'Ni izbranih uporabnikov za deblokado.', + 'unban_selected_success' => 'Izbrani uporabniki so bili uspeÅ¡no odblokirani.', + 'unsuspend' => 'Odsuspendiraj', + 'unsuspend_success' => 'Uporabnik ni veÄ suspendiran.', + 'unsuspend_confirm' => 'Odsuspendiram tega uporabnika?', + ], + 'settings' => [ + 'users' => 'Uporabniki', + 'menu_label' => 'Nastavitve za uporabnike', + 'menu_description' => 'Upravljanje z nastavitvami za uporabnike.', + 'activation_tab' => 'Aktivacija', + 'signin_tab' => 'Prijava', + 'registration_tab' => 'Registracija', + 'profile_tab' => 'Profil', + 'notifications_tab' => 'Obvestila', + 'allow_registration' => 'Dovoli registracijo uporabnikov', + 'allow_registration_comment' => 'ÄŒe je onemogoÄeno, lahko uporabnike ustvarijo le administratorji.', + 'activate_mode' => 'NaÄin aktivacije', + 'activate_mode_comment' => 'Izberite, na kakÅ¡en naÄin naj bo aktiviran uporabniÅ¡ki raÄun.', + 'activate_mode_auto' => 'Avtomatski', + 'activate_mode_auto_comment' => 'Aktivacija je avtomatska in se zgodi takoj po registraciji.', + 'activate_mode_user' => 'UporabniÅ¡ki', + 'activate_mode_user_comment' => 'Uporabnik sam aktivira svoj raÄun z uporabo e-poÅ¡te.', + 'activate_mode_admin' => 'Administratorski', + 'activate_mode_admin_comment' => 'Uporabnika lahko aktivira le administrator.', + 'require_activation' => 'Prijava zahteva aktivacijo', + 'require_activation_comment' => 'Uporabniki potrebujejo za prijavo aktiviran raÄun.', + 'use_throttle' => 'Blokiranje veÄkratnih prijav', + 'use_throttle_comment' => 'VeÄkratni ponovljeni neuspeÅ¡ni poskusi prijave bodo uporabnika zaÄasno suspendirali.', + 'use_register_throttle' => 'Blokiranje registracij', + 'use_register_throttle_comment' => 'PrepreÄi veÄ zaporednih registracij z istega IP naslova v kratkem Äasu.', + 'block_persistence' => 'PrepreÄi soÄasne prijave', + 'block_persistence_comment' => 'ÄŒe je omogoÄeno, se uporabniki ne morejo prijaviti v veÄ naprav hkrati.', + 'login_attribute' => 'Atribut prijave', + 'login_attribute_comment' => 'Izberite, kateri primarni atribut uporabnika naj bo uporabljen za prijavo.', + 'remember_login' => 'Zapomni si naÄin prijave', + 'remember_login_comment' => 'DoloÄite ali naj bo uporabniÅ¡ka seja obstojna.', + 'remember_always' => 'Vedno', + 'remember_never' => 'Nikoli', + 'remember_ask' => 'VpraÅ¡aj uporabnika ob prijavi', + ], + 'user' => [ + 'label' => 'Uporabnik', + 'id' => 'ID', + 'username' => 'UporabniÅ¡ko ime', + 'name' => 'Ime', + 'name_empty' => 'Anonimni uporabnik', + 'surname' => 'Priimek', + 'email' => 'E-poÅ¡ta', + 'created_at' => 'Registriran dne', + 'last_seen' => 'ZadnjiÄ viden', + 'is_guest' => 'Gost', + 'joined' => 'Prijavljen', + 'is_online' => 'Trenutno na spletu', + 'is_offline' => 'Trenutno ni na spletu', + 'send_invite' => 'PoÅ¡lji povabilo prek e-poÅ¡te', + 'send_invite_comment' => 'PoÅ¡lje pozdravno sporoÄilo, ki vsebuje podatke za prijavo.', + 'create_password' => 'Geslo', + 'create_password_comment' => 'Ustvarite novo geslo, ki se bo uporabljalo za prijavo.', + 'reset_password' => 'Ponastavi geslo', + 'reset_password_comment' => 'ÄŒe želite ponastaviti geslo tega uporabnika, vnesite tukaj novo geslo.', + 'confirm_password' => 'Potrditev gesla', + 'confirm_password_comment' => 'Za potrditev ponovno vnesite geslo.', + 'groups' => 'Skupine', + 'empty_groups' => 'Ni uporabniÅ¡kih skupin.', + 'avatar' => 'Avatar', + 'details' => 'Podrobnosti', + 'account' => 'RaÄun', + 'block_mail' => 'Blokiraj vso odhodno poÅ¡to, poslano temu uporabniku.', + 'status_guest' => 'Gost', + 'status_activated' => 'Aktiviran', + 'status_registered' => 'Registriran', + 'created_ip_address' => 'Ustvarjen IP naslov', + 'last_ip_address' => 'Zadnji IP naslov', + ], + 'group' => [ + 'label' => 'Skupina', + 'id' => 'ID', + 'name' => 'Ime', + 'description_field' => 'Opis', + 'code' => 'Koda', + 'code_comment' => 'Vnesite unikatno kodo za identifikacijo te skupine.', + 'created_at' => 'Ustvarjeno', + 'users_count' => 'Uporabniki', + ], + 'groups' => [ + 'menu_label' => 'Skupine', + 'all_groups' => 'Skupine uporabnikov', + 'new_group' => 'Nova skupina', + 'delete_selected_confirm' => 'Ali ste prepriÄani, da želite izbrisati izbrane skupine?', + 'list_title' => 'Upravljanje skupin', + 'delete_confirm' => 'Ali ste prepriÄani, da želite izbrisati to skupino?', + 'delete_selected_success' => 'Izbrane skupine so uspeÅ¡no izbrisane.', + 'delete_selected_empty' => 'Ni izbranih skupin za izbris.', + 'return_to_list' => 'Nazaj na seznam skupin', + 'return_to_users' => 'Nazaj na seznam uporabnikov', + 'create_title' => 'Ustvari skupino uporabnikov', + 'update_title' => 'Uredi skupino uporabnikov', + 'preview_title' => 'Predogled skupine uporabnikov', + ], + 'login' => [ + 'attribute_email' => 'E-poÅ¡ta', + 'attribute_username' => 'UporabniÅ¡ko ime', + ], + 'account' => [ + 'account' => 'RaÄun', + 'account_desc' => 'Upravljanje uporabnika.', + 'banned' => 'Oprostite, ta uporabnik trenutno ni aktiviran. Prosimo, kontaktirajte nas za nadaljnjo pomoÄ.', + 'redirect_to' => 'Preusmeritev na', + 'redirect_to_desc' => 'Stran, na katero bo uporabnik preusmerjen po posodobitvi profila, po prijavi ali po registraciji.', + 'code_param' => 'Parameter aktivacijske kode', + 'code_param_desc' => 'Parameter v URL-ju strani, ki se uporablja za aktivacijsko kodo registracije.', + 'force_secure' => 'Vsili zaÅ¡Äitni protokol', + 'force_secure_desc' => 'URL vedno preusmeri s shemo HTTPS.', + 'invalid_user' => 'Uporabnika ni mogoÄe najti glede na podane poverilnice.', + 'invalid_activation_code' => 'Podana je neveljavna aktivacijska koda.', + 'invalid_deactivation_pass' => 'Geslo, ki ste ga vnesli, je neveljavno.', + 'invalid_current_pass' => 'Trenutno geslo, ki ste ga vnesli, je neveljavno.', + 'success_activation' => 'VaÅ¡ raÄun je uspeÅ¡no aktiviran.', + 'success_deactivation' => 'VaÅ¡ raÄun je bil uspeÅ¡no deaktiviran. Žal nam je, ker nas zapuÅ¡Äate!', + 'success_saved' => 'Nastavitve so uspeÅ¡no shranjene.', + 'login_first' => 'Najprej se morate prijaviti.', + 'already_active' => 'VaÅ¡ raÄun je že aktiviran.', + 'activation_email_sent' => 'Aktivacijsko sporoÄilo je bilo poslano na vaÅ¡ e-poÅ¡tni naslov.', + 'registration_disabled' => 'Registracije so trenutno onemogoÄene.', + 'registration_throttled' => 'Registracija je trenutno onemogoÄena. Prosimo, poskusite zopet kasneje.', + 'sign_in' => 'Prijava', + 'register' => 'Registracija', + 'full_name' => 'Polno ime', + 'email' => 'E-poÅ¡ta', + 'password' => 'Geslo', + 'login' => 'Prijava', + 'new_password' => 'Novo geslo', + 'new_password_confirm' => 'Potrdite novo geslo', + 'update_requires_password' => 'Posodobitev zahteva potrditev gesla', + 'update_requires_password_comment' => 'Pri spreminjanju profila od uporabnika zahteva trenutno geslo.', + ], + 'reset_password' => [ + 'reset_password' => 'Ponastavitev gesla', + 'reset_password_desc' => 'Obrazec za pozabljeno geslo.', + 'code_param' => 'Parameter za ponastavitev', + 'code_param_desc' => 'Parameter v URL-ju strani, ki se uporablja za ponastavitev gesla.', + ], + 'session' => [ + 'session' => 'Seja', + 'session_desc' => 'Namestitev uporabniÅ¡ke seje, ki lahko omeji dostop do strani.', + 'security_title' => 'Dovoljenje za dostop', + 'security_desc' => 'DoloÄite, kdo lahko dostopa do te strani.', + 'all' => 'Vsi', + 'users' => 'Uporabniki', + 'guests' => 'Gosti', + 'allowed_groups_title' => 'Dovoljenje za skupine', + 'allowed_groups_description' => 'DoloÄite, katere skupine lahko dostopajo do te strani. ÄŒe ne izberete nobene, imajo dovoljenje vse skupine.', + 'redirect_title' => 'Preusmeritev na stran', + 'redirect_desc' => 'DoloÄite stran, na katero je preusmerjen uporabnik, Äe je dostop onemogoÄen.', + 'logout' => 'UspeÅ¡no ste se odjavili.', + 'stop_impersonate_success' => 'Uporabnika ne impersonirate veÄ.', + ], +]; diff --git a/plugins/rainlab/user/lang/sv/lang.php b/plugins/rainlab/user/lang/sv/lang.php new file mode 100644 index 0000000..e3ad8d0 --- /dev/null +++ b/plugins/rainlab/user/lang/sv/lang.php @@ -0,0 +1,205 @@ + [ + 'name' => 'Användare', + 'description' => 'Hantera front-end användare.', + 'tab' => 'Användare', + 'access_users' => 'Hantera användare', + 'access_groups' => 'Hantera användargrupper', + 'access_settings' => 'Hantera användarinställningar', + 'impersonate_user' => 'Personifiera Användare' + ], + 'users' => [ + 'menu_label' => 'Användare', + 'all_users' => 'Alla användare', + 'new_user' => 'Ny användare', + 'list_title' => 'Hantera användare', + 'trashed_hint_title' => 'Användaren har avaktiverat sitt konto', + 'trashed_hint_desc' => 'Den här användaren har inaktiverat sitt konto och vill inte längre visas pÃ¥ webbplatsen. De kan Ã¥terställa sitt konto när som helst genom att logga in igen. ', + 'banned_hint_title' => 'Användaren har blivit bannad', + 'banned_hint_desc' => 'Den här användaren har blivit bannad av en administratör och kommer inte att kunna logga in.', + 'guest_hint_title' => 'Detta är en gästanvändare', + 'guest_hint_desc' => 'Den här användaren är endast lagrad för referensändamÃ¥l och mÃ¥ste registreras innan du loggar in.', + 'activate_warning_title' => 'Användare inte aktiverad!', + 'activate_warning_desc' => 'Den här användaren har inte aktiverats och kan inte logga in.', + 'activate_confirm' => 'Vill du verkligen aktivera den här användaren?', + 'activated_success' => 'Användaren har aktiverats', + 'activate_manually' => 'Aktivera den här användaren manuellt', + 'convert_guest_confirm' => 'Konvertera denna gäst till en användare?', + 'convert_guest_manually' => 'Konvertera till registrerad användare', + 'convert_guest_success' => 'Användaren har konverterats till ett registrerat konto', + 'impersonate_user' => 'Personifiera användaren', + 'impersonate_confirm' => 'Impersonera den här användaren? Du kan Ã¥tergÃ¥ till ditt ursprungliga tillstÃ¥nd genom att logga ut. ', + 'impersonate_success' => 'Du är nu efterliknar den här användaren', + 'delete_confirm' => 'Vill du verkligen radera den här användaren?', + 'unban_user' => 'Unban den här användaren', + 'unban_confirm' => 'Vill du verkligen avbryta denna användare?', + 'unbanned_success' => 'Användaren har blivit unbanned', + 'return_to_list' => 'Ã…tervänd till användarlistan', + 'update_details' => 'Uppdatera detaljer', + 'bulk_actions' => 'MassÃ¥tgärder', + 'delete_selected' => 'Radera vald', + 'delete_selected_confirm' => 'Ta bort de valda användarna?', + 'delete_selected_empty' => 'Det finns inga utvalda användare att ta bort.', + 'delete_selected_success' => 'Ta bort de valda användarna framgÃ¥ngsrikt.', + 'activate_selected' => 'Aktivera vald', + 'activate_selected_confirm' => 'Aktivera de valda användarna?', + 'activate_selected_empty' => 'Det finns inga utvalda användare att aktivera.', + 'activate_selected_success' => 'Aktiverade de valda användarna framgÃ¥ngsrikt.', + 'deactivate_selected' => 'Inaktivera vald', + 'deactivate_selected_confirm' => 'Inaktivera de valda användarna?', + 'deactivate_selected_empty' => 'Det finns inga utvalda användare att avaktivera.', + 'deactivate_selected_success' => 'Deaktiverade de valda användarna framgÃ¥ngsrikt.', + 'restore_selected' => 'Ã…terställ valda', + 'restore_selected_confirm' => 'Ã…terställ de valda användarna?', + 'restore_selected_empty' => 'Det finns inga utvalda användare att Ã¥terställa.', + 'restore_selected_success' => 'Ã…terställde de valda användarna framgÃ¥ngsrikt.', + 'ban_selected' => 'Ban vald', + 'ban_selected_confirm' => 'Förbjud de valda användarna?', + 'ban_selected_empty' => 'Det finns inga utvalda användare att förbuda.', + 'ban_selected_success' => 'Förbannade de valda användarna framgÃ¥ngsrikt.', + 'unban_selected' => 'Unban vald', + 'unban_selected_confirm' => 'Unban de valda användarna?', + 'unban_selected_empty' => 'Det finns inga utvalda användare att unban.', + 'unban_selected_success' => 'Unbanned de utvalda användarna.', + ], + 'settings' => [ + 'users' => 'Användare', + 'menu_label' => 'Användarinställningar', + 'menu_description' => 'Hantera användarbaserade inställningar.', + 'activation_tab' => 'Aktivering', + 'signin_tab' => 'Logga in', + 'registration_tab' => 'Registrering', + 'notifications_tab' => 'Meddelanden', + 'allow_registration' => 'TillÃ¥t användarregistrering', + 'allow_registration_comment' => 'Om detta är inaktiverat kan användare endast skapas av administratörer.', + 'activate_mode' => 'Aktiveringsläge', + 'activate_mode_comment' => 'Välj hur ett användarkonto ska aktiveras.', + 'activate_mode_auto' => 'Automatisk', + 'activate_mode_auto_comment' => 'Aktiveras automatiskt vid registrering.', + 'activate_mode_user' => 'Användare', + 'activate_mode_user_comment' => 'Användaren aktiverar sitt eget konto via e-post.', + 'activate_mode_admin' => 'Administratör', + 'activate_mode_admin_comment' => 'Endast en administratör kan aktivera en användare.', + 'require_activation' => 'Logga in kräver aktivering', + 'require_activation_comment' => 'Användare mÃ¥ste ha ett aktiverat konto för att logga in.', + 'use_throttle' => 'Upprepningsförsök', + 'use_throttle_comment' => 'Upprepade misslyckade inloggningsförsök kommer tillfälligt att stoppa användaren.', + 'block_persistence' => 'Förhindra samtidiga sessioner', + 'block_persistence_comment' => 'När aktiverade användare inte kan logga in pÃ¥ flera enheter samtidigt.', + 'login_attribute' => 'Logga in egenskaper', + 'login_attribute_comment' => 'Välj vilken primär användarinfo som ska användas för inloggning.', + ], + 'user' => [ + 'label' => 'Användare', + 'id' => 'ID', + 'username' => 'Användarnamn', + 'name' => 'Namn', + 'name_empty' => 'Anonym', + 'surname' => 'Efternamn', + 'email' => 'Email', + 'created_at' => 'Registrerad', + 'last_seen' => 'Senast sett', + 'is_guest' => 'Gäst', + 'joined' => 'Anställd', + 'is_online' => 'Online nu', + 'is_offline' => 'För närvarande offline', + 'send_invite' => 'Skicka inbjudan via e-post', + 'send_invite_comment' => 'Skickar ett välkomstmeddelande som innehÃ¥ller inloggnings- och lösenordsinformation.', + 'create_password' => 'Skapa lösenord', + 'create_password_comment' => 'Ange ett nytt lösenord som används för inloggning.', + 'reset_password' => 'Ã…terställ lösenord', + 'reset_password_comment' => 'För att Ã¥terställa användarens lösenord, ange ett nytt lösenord här.', + 'confirm_password' => 'Bekräftelse av lösenord', + 'confirm_password_comment' => 'Ange lösenordet igen för att bekräfta det.', + 'groups' => 'Grupper', + 'empty_groups' => 'Det finns inga användargrupper tillgängliga.', + 'avatar' => 'Avatar', + 'details' => 'Detaljer', + 'account' => 'Konto', + 'block_mail' => 'Blockera alla utgÃ¥ende mail som skickas till den här användaren.', + 'status_guest' => 'Gäst', + 'status_activated' => 'Aktiverad', + 'status_registered' => 'Registrerad', + ], + 'group' => [ + 'label' => 'Grupp', + 'id' => 'ID', + 'name' => 'Namn', + 'description_field' => 'Beskrivning', + 'code' => 'Kod', + 'code_comment' => 'Ange en unik kod som används för att identifiera den här gruppen.', + 'created_at' => 'Skapat', + 'users_count' => 'Användare' + ], + 'groups' => [ + 'menu_label' => 'Grupper', + 'all_groups' => 'Användargrupper', + 'new_group' => 'Ny grupp', + 'delete_selected_confirm' => 'Vill du verkligen radera valda grupper?', + 'list_title' => 'Hantera grupper', + 'delete_confirm' => 'Vill du verkligen radera den här gruppen?', + 'delete_selected_success' => 'Tog bort de valda grupperna framgÃ¥ngsrikt', + 'delete_selected_empty' => 'Det finns inga valda grupper att radera.', + 'return_to_list' => 'Tillbaka till grupplista', + 'return_to_users' => 'Tillbaka till användarlistan', + 'create_title' => 'Skapa användargrupp', + 'update_title' => 'Redigera användargrupp', + 'preview_title' => 'Förhandsgranska användargrupp' + ], + 'login' => [ + 'attribute_email' => 'Email', + 'attribute_username' => 'Användarnamn' + ], + 'account' => [ + 'account' => 'Konto', + 'account_desc' => 'Användarhanteringsformulär.', + 'banned' => 'Tyvärr, den här användaren är för närvarande inte aktiverad. Vänligen kontakta oss för ytterligare hjälp. ', + 'redirect_to' => 'Omdirigera till', + 'redirect_to_desc' => 'Sidnamn för att omdirigera till efter uppdatering, logga in eller registrera.', + 'code_param' => 'Aktiveringskod Param', + 'code_param_desc' => 'Sidadressadressparametern som används för registreringsaktiveringskoden', + 'force_secure' => 'Tvinga säkert protokoll', + 'force_secure_desc' => 'Omdirigera alltid URL-adressen med HTTPS-schemat.', + 'invalid_user' => 'En användare kunde inte hittas med angivna referenser.', + 'invalid_activation_code' => 'Ogiltig aktiveringskod medföljer.', + 'invalid_deactivation_pass' => 'Lösenordet du angav var ogiltigt.', + 'success_activation' => 'Aktiverat ditt konto.', + 'success_deactivation' => 'Inaktiverade ditt konto framgÃ¥ngsrikt. TrÃ¥kigt att du lämnar oss! ', + 'success_saved' => 'Inställningar sparades framgÃ¥ngsrikt!', + 'login_first' => 'Du mÃ¥ste vara inloggad först!', + 'already_active' => 'Ditt konto är redan aktiverat!', + 'activation_email_sent' => 'Ett aktiverings-e-postmeddelande har skickats till din e-postadress.', + 'registration_disabled' => 'Registreringar är för närvarande inaktiverade.', + 'sign_in' => 'Logga in', + 'register' => 'Registrera', + 'full_name' => 'Fullständigt namn', + 'email' => 'Email', + 'password' => 'Lösenord', + 'login' => 'Logga in', + 'new_password' => 'Nytt lösenord', + 'new_password_confirm' => 'Bekräfta nytt lösenord' + ], + 'reset_password' => [ + 'reset_password' => 'Ã…terställ lösenord', + 'reset_password_desc' => 'Glömt lösenordsformulär.', + 'code_param' => 'Ã…terställ kodparam', + 'code_param_desc' => 'Sidadressparametern som används för Ã¥terställningskoden' + ], + 'session' => [ + 'session' => 'Session', + 'session_desc' => 'Lägger till användarsessionen pÃ¥ en sida och kan begränsa sidÃ¥tkomst.', + 'security_title' => 'TillÃ¥t bara', + 'security_desc' => 'Vem fÃ¥r komma Ã¥t denna sida.', + 'all' => 'Alla', + 'users' => 'Användare', + 'guests' => 'Gäster', + 'allowed_groups_title' => 'TillÃ¥t grupper', + 'allowed_groups_description' => 'Välj tillÃ¥tna grupper eller ingen för att tillÃ¥ta alla grupper', + 'redirect_title' => 'Omdirigera till', + 'redirect_desc' => 'Sidnamn att omdirigera om Ã¥tkomst nekas.', + 'logout' => 'Du har blivit framgÃ¥ngsrik utloggad!', + 'stop_impersonate_success' => 'Du personifierar inte längre en användare.', + ] +]; diff --git a/plugins/rainlab/user/lang/tr/lang.php b/plugins/rainlab/user/lang/tr/lang.php new file mode 100644 index 0000000..04350d2 --- /dev/null +++ b/plugins/rainlab/user/lang/tr/lang.php @@ -0,0 +1,222 @@ + [ + 'name' => 'Üye', + 'description' => 'Ön-yüz üye yönetimi.', + 'tab' => 'Üyeler', + 'access_users' => 'Üyeleri Yönet', + 'access_groups' => 'Üye Gruplarını Yönet', + 'access_settings' => 'Üye Ayarlarını Yönet', + 'impersonate_user' => 'Üye Gibi Gezin', + ], + 'users' => [ + 'menu_label' => 'Üyeler', + 'all_users' => 'Bütün Üyeler', + 'new_user' => 'Yeni Üye', + 'list_title' => 'Üyeleri Yönet', + 'trashed_hint_title' => 'Üye hesabını pasifleÅŸtirmiÅŸ', + 'trashed_hint_desc' => 'Üye hesabını pasifleÅŸtirmiÅŸ ve bu sitede görünmek istemiyor. Tekrar hesabına giriÅŸ yaparak hesabını istediÄŸi zaman aktifleÅŸtirebilir.', + 'banned_hint_title' => 'Üye engellendi.', + 'banned_hint_desc' => 'Üye bir yönetici tarafından engellendi ve giriÅŸ yapamayacak.', + 'guest_hint_title' => 'Bu üye ziyaretçi.', + 'guest_hint_desc' => 'Bu üye ziyaretçi olarak eklenmiÅŸ ve giriÅŸ yapabilmesi için kayıt olması gerekiyor.', + 'activate_warning_title' => 'Üye hesabı aktif edilmemiÅŸ!', + 'activate_warning_desc' => 'Bu üye hesabı aktif edilmedi ve oturum açamayacaktır.', + 'activate_confirm' => 'Bu üyeyi gerçekten aktif etmek istediÄŸinize emin misiniz?', + 'activated_success' => 'Üye aktifleÅŸtirildi', + 'activate_manually' => 'Bu üyeyi aktif et', + 'convert_guest_confirm' => 'Ziyaretçiyi üyeye çevirmek istiyor musunuz?', + 'convert_guest_manually' => 'Kayıtlı üyeye çevir', + 'convert_guest_success' => 'Ziyaretçi, kayıtlı üyeye çevrildi.', + 'impersonate_user' => 'Üye Gibi Gezin', + 'impersonate_confirm' => 'Bu üye gibi giriÅŸ yapmak istediÄŸinize emin misiniz? Çıkış yaparak tekrar orjinal halinize dönebilirsiniz.', + 'impersonate_success' => 'Åžimdi üye gibi gezinebilirsiniz.', + 'delete_confirm' => 'Bu üyeyi gerçekten silmek istediÄŸinize emin misiniz?', + 'unban_user' => 'Üyenin engelini kaldır', + 'unban_confirm' => 'Bu üyenin engelini kaldırmak istediÄŸinize emin misiniz?', + 'unbanned_success' => 'Üyenin engeli kaldırıldı', + 'return_to_list' => 'Üye listesine geri dön', + 'update_details' => 'Detayları deÄŸiÅŸtir', + 'bulk_actions' => 'Toplu iÅŸlemler', + 'delete_selected' => 'Seçileni sil', + 'delete_selected_confirm' => 'Seçili üyeleri sil?', + 'delete_selected_empty' => 'Silmek için seçili üye yok.', + 'delete_selected_success' => 'Seçili üyeler baÅŸarıyla silindi.', + 'activate_selected' => 'Seçileni etkinleÅŸtir', + 'activate_selected_confirm' => 'Seçili kullanıcılar etkinleÅŸtirilsin mi?', + 'activate_selected_empty' => 'EtkinleÅŸtirilecek seçili kullanıcı yok.', + 'activate_selected_success' => 'Seçilen kullanıcılar baÅŸarıyla etkinleÅŸtirildi.', + 'deactivate_selected' => 'Seçileni pasifleÅŸtir', + 'deactivate_selected_confirm' => 'Seçilen üyeler pasifleÅŸtirilsin mi?', + 'deactivate_selected_empty' => 'PasifleÅŸtirmek için üye seçmelisiniz.', + 'deactivate_selected_success' => 'Seçilen üyeler pasifleÅŸtirildi.', + 'restore_selected' => 'Seçileni aktifleÅŸtir', + 'restore_selected_confirm' => 'Seçilen üyeler aktifleÅŸtirilsin mi?', + 'restore_selected_empty' => 'AktifleÅŸtirmek için üye seçmelisiniz.', + 'restore_selected_success' => 'Seçilen üyeler aktifleÅŸtirildi.', + 'ban_selected' => 'Seçileni engelle', + 'ban_selected_confirm' => 'Seçilen üyeler engellensin mi?', + 'ban_selected_empty' => 'Engellemek için üye seçmelisiniz.', + 'ban_selected_success' => 'Seçilen üyeler engellendi.', + 'unban_selected' => 'Seçilenin engelini kaldır', + 'unban_selected_confirm' => 'Seçilen üyelerin engeli kaldırılsın mi?', + 'unban_selected_empty' => 'Engeli kaldırmak için üye seçmelisiniz.', + 'unban_selected_success' => 'Seçilen üyelerin engeli kaldırıldı.', + 'unsuspend' => 'Askıya alma', + 'unsuspend_success' => 'Üye askıya alındı.', + 'unsuspend_confirm' => 'Üye askıya alınsın mı?' + ], + 'settings' => [ + 'users' => 'Üyeler', + 'menu_label' => 'Üye ayarları', + 'menu_description' => 'Üye bazlı ayarları yönetin.', + 'activation_tab' => 'Aktivasyon', + 'signin_tab' => 'Oturum Açma', + 'registration_tab' => 'Kayıt', + 'profile_tab' => 'Profil', + 'notifications_tab' => 'Bildirimler', + 'allow_registration' => 'Üye kaydını aktifleÅŸtir', + 'allow_registration_comment' => 'EÄŸer bu seçenek pasifleÅŸtirilirse sadece yöneticiler tarafından üye kaydı yapılabilecektir.', + 'min_password_length' => 'Minimum ÅŸifre uzunluÄŸu', + 'min_password_length_comment' => 'Üye ÅŸifresi için gereken minimum ÅŸifre uzunluÄŸu', + 'activate_mode' => 'Aktivasyon Modu', + 'activate_mode_comment' => 'Üyenin nasıl aktif edileceÄŸini seçin.', + 'activate_mode_auto' => 'Otomatik', + 'activate_mode_auto_comment' => 'Üye olduÄŸu an aktif edilsin.', + 'activate_mode_user' => 'Üye', + 'activate_mode_user_comment' => 'Eposta adresini kullanarak aktif etsin.', + 'activate_mode_admin' => 'Yönetici', + 'activate_mode_admin_comment' => 'Sadece yöneticiler aktif edebilsin.', + 'require_activation' => 'Üye giriÅŸleri aktivasyon gerektirsin', + 'require_activation_comment' => 'Üyeler oturum açabilmek için aktif edilmiÅŸ bir hesaba sahip olmalıdırlar.', + 'use_throttle' => 'BoÄŸma GiriÅŸimleri', + 'use_throttle_comment' => 'Tekrarlayan hatalı giriÅŸlerde kısa süreliÄŸine üyeyi askıya al.', + 'block_persistence' => 'EÅŸzamanlı oturumları engelle', + 'block_persistence_comment' => 'EtkinleÅŸtirildiÄŸinde, kullanıcılar aynı anda birden fazla cihazda oturum açamazlar.', + 'login_attribute' => 'Oturum Açma Yöntemi', + 'login_attribute_comment' => 'Üye giriÅŸlerinde hangi üye detayının kullanılacağını seçin.', + 'remember_login' => 'Åžifre hatırlama modu', + 'remember_login_comment' => 'Üye oturumu kalıcı olsun.', + 'remember_always' => 'Her zaman', + 'remember_never' => 'Hiçbir zaman', + 'remember_ask' => 'Üye giriÅŸi sırasında sor', + ], + 'user' => [ + 'label' => 'User', + 'id' => 'ID', + 'username' => 'Üye Adı', + 'name' => 'Adı', + 'name_empty' => '-İsimsiz-', + 'surname' => 'Soyadı', + 'email' => 'Eposta', + 'created_at' => 'Kayıtlı', + 'last_seen' => 'Son görülme', + 'is_guest' => 'Ziyaretçi', + 'joined' => 'Katılım Tarihi', + 'is_online' => 'Åžuan çevrimiçi', + 'is_offline' => 'Åžuan çevrimdışı', + 'send_invite' => 'E-mail ile davet gönder', + 'send_invite_comment' => 'GiriÅŸ bilgilerinin bulunduÄŸu bir e-mail gönder.', + 'create_password' => 'Åžifre oluÅŸtur', + 'create_password_comment' => 'GiriÅŸ için bir ÅŸifre oluÅŸturun.', + 'reset_password' => 'Åžifre sıfırla', + 'reset_password_comment' => 'Bu üyenin parolasını sıfırlamak için buraya yenisini girin.', + 'confirm_password' => 'Parola tekrar', + 'confirm_password_comment' => 'Sıfırlamayı onaylamak için ÅŸifreyi tekrar girin.', + 'groups' => 'Gruplar', + 'empty_groups' => 'Gösterilecek grup yok.', + 'avatar' => 'Avatar', + 'details' => 'Detaylar', + 'account' => 'Hesap', + 'block_mail' => 'Bu üyenin mail göndermesini engelle.', + 'status_guest' => 'Ziyaretçi', + 'status_activated' => 'Aktif', + 'status_registered' => 'Kayıtlı', + 'created_ip_address' => 'Kayıt olduÄŸu IP Adresi', + 'last_ip_address' => 'Son IP Adresi', + ], + 'group' => [ + 'label' => 'Grup', + 'id' => 'No', + 'name' => 'İsim', + 'description_field' => 'Açıklama', + 'code' => 'Kod', + 'code_comment' => 'Bu grubu tanımlayan eÅŸsiz bir kod girin.', + 'created_at' => 'OluÅŸturulma', + 'users_count' => 'Üyeler', + ], + 'groups' => [ + 'menu_label' => 'Gruplar', + 'all_groups' => 'Üye Grupları', + 'new_group' => 'Yeni Grup', + 'delete_selected_confirm' => 'Seçilen grupları silmek istediÄŸinize emin misiniz?', + 'list_title' => 'Grupları Yönet', + 'delete_confirm' => 'Bu grubu silmek istediÄŸinize emin misiniz?', + 'delete_selected_success' => 'Seçilen gruplar silindi.', + 'delete_selected_empty' => 'Silinecek grup seçmelisiniz.', + 'return_to_list' => 'Grup listesine dön', + 'return_to_users' => 'Üye listesine dön', + 'create_title' => 'Üye grubu oluÅŸtur', + 'update_title' => 'Üye grubunu düzenle', + 'preview_title' => 'Grubu önizle', + ], + 'login' => [ + 'attribute_email' => 'Eposta', + 'attribute_username' => 'Üye Adı', + ], + 'account' => [ + 'account' => 'Hesap', + 'account_desc' => 'Üye yönetimi formu.', + 'banned' => 'Maalesef, bu kullanıcı ÅŸu anda etkin deÄŸil. Daha fazla yardım için lütfen bizimle iletiÅŸime geçin.', + 'redirect_to' => 'Yönlendir', + 'redirect_to_desc' => 'Güncellemeden sonra yönlendirilecek sayfanın adı, oturum aç ya da kayıt ol.', + 'code_param' => 'Aktivasyon Kodu Parametresi', + 'code_param_desc' => 'Üyelik aktivasyon kodu için sayfanın URL parametresi kullanılır.', + 'force_secure' => 'Güvenli protokole zorla', + 'force_secure_desc' => 'URL’yi her zaman HTTPS ÅŸemasına yönlendirin.', + 'invalid_user' => 'Girilen bilgilerle eÅŸleÅŸen bir üye yok.', + 'invalid_activation_code' => 'Geçersiz aktivasyon kodu', + 'invalid_current_pass' => 'Mevcut ÅŸifrenizi hatalı girdiniz.', + 'invalid_deactivation_pass' => 'GirdiÄŸiniz ÅŸifre geçersiz.', + 'success_activation' => 'Hesabınız baÅŸarıyla aktifleÅŸtirildi.', + 'success_deactivation' => 'Hesabınız pasifleÅŸtirildi. Aramıza tekrar bekleriz!', + 'success_saved' => 'Ayarlar baÅŸarıyla kaydedildi!', + 'login_first' => 'Önce oturum açmalısınız!', + 'already_active' => 'Hesabın zaten aktifleÅŸtirildi!', + 'activation_email_sent' => 'Tanımladığınız eposta adresine aktivasyon maili gönderildi.', + 'registration_disabled' => 'Üye kaydı geçici olarak durduruldu.', + 'registration_throttled' => 'Üye kayıt iÅŸleminiz kısıtlandı ve geçersiz oldu. Lütfen daha sonra tekrar deneyin.', + 'sign_in' => 'Oturum Aç', + 'register' => 'Kayıt Ol', + 'full_name' => 'Tam İsim', + 'email' => 'Email', + 'password' => 'Parola', + 'login' => 'Oturum Aç', + 'new_password' => 'Yeni Parola', + 'new_password_confirm' => 'Yeni Åžifre Onayla', + 'update_requires_password' => 'Güncelleme sırasında onay gereksin', + 'update_requires_password_comment' => 'Üye bilgi güncelleme ekranında mevcut ÅŸifre zorunlu olsun.' + ], + 'reset_password' => [ + 'reset_password' => 'Parolanızı Sıfırlayın', + 'reset_password_desc' => 'Unutulan ÅŸifreyi sıfırlama formu.', + 'code_param' => 'Sıfırlama Kodu Parametresi', + 'code_param_desc' => 'Sıfırlama kodu için sayfanın URL parametresi kullanılır.', + ], + 'session' => [ + 'session' => 'Oturum', + 'session_desc' => 'Üye oturumlarını sayfaya ekler ve sayfaya eriÅŸimi kısıtlayın.', + 'security_title' => 'Görüntüleme İzni', + 'security_desc' => 'Bu sayfaya eriÅŸim izni olanlar.', + 'all' => 'Hepsi', + 'users' => 'Üyeler', + 'guests' => 'Misafirler', + 'allowed_groups_title' => 'Gruplara izin ver', + 'allowed_groups_description' => 'İzin verilecek grupları seçin, veya "hiçbiri" seçerek tüm gruplara izin verin.', + 'redirect_title' => 'Yönlendir ', + 'redirect_desc' => 'EriÅŸimi engelliyse yönlendirilecek sayfa.', + 'logout' => 'BaÅŸarıyla çıkış yaptınız!', + 'stop_impersonate_success' => 'Artık üye gibi gezinmiyorsunuz. Kendi hesabınızı kullanabilirsiniz.', + ], +]; diff --git a/plugins/rainlab/user/lang/zh-cn/lang.php b/plugins/rainlab/user/lang/zh-cn/lang.php new file mode 100644 index 0000000..8c3c859 --- /dev/null +++ b/plugins/rainlab/user/lang/zh-cn/lang.php @@ -0,0 +1,192 @@ + [ + 'name' => '用户', + 'description' => '用户管ç†.', + 'tab' => '用户', + 'access_users' => '管ç†ç”¨æˆ¶', + 'access_groups' => '管ç†ç”¨æˆ·ç»„', + 'access_settings' => '管ç†ç”¨æˆ·è®¾ç½®', + ], + 'users' => [ + 'menu_label' => '用户', + 'all_users' => '所有用户', + 'new_user' => '添加新用户', + 'list_title' => '管ç†ç”¨æˆ·', + 'trashed_hint_title' => '用户已åœç”¨å…¶å¸æˆ·', + 'trashed_hint_desc' => '此用户已åœç”¨å…¶å¸æˆ·ï¼Œä¸å†å¸Œæœ›å‡ºçŽ°åœ¨ç½‘ç«™ä¸Šã€‚ä»–ä»¬å¯ä»¥åœ¨ä»»ä½•æ—¶å€™é€šè¿‡é‡æ–°ç™»å½•æ¥æ¢å¤å¸æˆ·ã€‚', + 'banned_hint_title' => 'ç”¨æˆ·å·²è¢«ç¦æ­¢', + 'banned_hint_desc' => '该用户已被管ç†å‘˜ç¦æ­¢ï¼Œæ— æ³•登录。', + 'guest_hint_title' => '这是一个游客用户', + 'guest_hint_desc' => '此用户仅供å‚考,在登录å‰éœ€è¦æ³¨å†Œã€‚', + 'activate_warning_title' => '用户未激活!', + 'activate_warning_desc' => '用户未激活,无法登录.', + 'activate_confirm' => '确认激活该用户?', + 'activated_success' => '用户激活æˆåŠŸ!', + 'activate_manually' => '手动激活该用户', + 'convert_guest_confirm' => '转æ¢è®¿å®¢ä¸ºç”¨æˆ·å—?', + 'convert_guest_manually' => '转æ¢ä¸ºæ³¨å†Œç”¨æˆ·', + 'convert_guest_success' => '用户已转æ¢ä¸ºæ³¨å†Œå¸æˆ·', + 'delete_confirm' => '确认删除该用户?', + 'unban_user' => 'è§£ç¦ç”¨æˆ·', + 'unban_confirm' => '确定解ç¦è¯¥ç”¨æˆ·å—?', + 'unbanned_success' => '用户已ç»è§£ç¦', + 'return_to_list' => '返回用户列表', + 'update_details' => '更新详细信æ¯', + 'bulk_actions' => 'æ‰¹é‡æ“作', + 'delete_selected' => '删除选中', + 'delete_selected_confirm' => '删除所选用户?', + 'delete_selected_empty' => '未选择任何用户.', + 'delete_selected_success' => 'æˆåŠŸåˆ é™¤æ‰€é€‰ç”¨æˆ·.', + 'deactivate_selected' => 'åœç”¨é€‰ä¸­', + 'deactivate_selected_confirm' => '确定åœç”¨é€‰ä¸­çš„用户å—?', + 'deactivate_selected_empty' => '没有选中任何è¦åœç”¨çš„用户。', + 'deactivate_selected_success' => 'æˆåŠŸåœç”¨é€‰å®šçš„用户。', + 'restore_selected' => 'æ¢å¤é€‰ä¸­', + 'restore_selected_confirm' => '确定æ¢å¤é€‰ä¸­çš„用户å—?', + 'restore_selected_empty' => 'æ²¡æœ‰é€‰ä¸­ä»»ä½•è¦æ¢å¤çš„用户。', + 'restore_selected_success' => 'æˆåŠŸæ¢å¤é€‰ä¸­é€‰ä¸­çš„用户。', + 'ban_selected' => 'ç¦ç”¨é€‰ä¸­', + 'ban_selected_confirm' => 'ç¡®å®šç¦æ­¢é€‰ä¸­çš„用户å—?', + 'ban_selected_empty' => '没有选中的用户需è¦ç¦ç”¨ã€‚', + 'ban_selected_success' => 'æˆåŠŸç¦ç”¨é€‰ä¸­ç”¨æˆ·', + 'unban_selected' => 'å¯ç”¨é€‰ä¸­', + 'unban_selected_confirm' => '确定å¯ç”¨é€‰ä¸­çš„用户å—?', + 'unban_selected_empty' => '没有选中的用户å¯ä»¥å¯ç”¨ã€‚', + 'unban_selected_success' => 'æˆåŠŸå¯ç”¨é€‰ä¸­çš„用户。', + 'activating' => '激活中...', + ], + 'settings' => [ + 'users' => '用户', + 'menu_label' => '用户选项', + 'menu_description' => '管ç†ç”¨æˆ·é€‰é¡¹.', + 'activation_tab' => '激活', + 'signin_tab' => '登录', + 'registration_tab' => '注册', + 'notifications_tab' => 'æé†’', + 'allow_registration' => 'å…许用户注册', + 'allow_registration_comment' => '如果ç¦ç”¨æ³¨å†Œï¼Œç”¨æˆ·åªèƒ½ç”±ç®¡ç†å‘˜åˆ›å»ºã€‚', + 'activate_mode' => '激活模å¼', + 'activate_mode_comment' => '选择激活方å¼.', + 'activate_mode_auto' => '自动', + 'activate_mode_auto_comment' => '注册æˆåŠŸåŽè‡ªåŠ¨æ¿€æ´».', + 'activate_mode_user' => '用户', + 'activate_mode_user_comment' => '邮件激活.', + 'activate_mode_admin' => '管ç†å‘˜', + 'activate_mode_admin_comment' => '管ç†å‘˜æ¿€æ´».', + 'welcome_template' => '欢迎模版', + 'welcome_template_comment' => '用户激活æˆåŠŸåŽé‚®ä»¶æ¨¡ç‰ˆ.', + 'require_activation' => '选项', + 'require_activation_comment' => 'ç”¨æˆ·å¿…é¡»æ¿€æ´»åŽæ‰èƒ½ç™»å½•.', + 'use_throttle' => '登录é™åˆ¶', + 'use_throttle_comment' => '用户é‡å¤ç™»å½•失败时ç¦ç”¨ç”¨æˆ·.', + 'login_attribute' => '登录字段', + 'login_attribute_comment' => '选择用户登录类型.', + 'no_mail_template' => 'ä¸å‘é€é‚®ä»¶æé†’', + 'hint_templates' => 'ä½ å¯ä»¥é€šè¿‡ç®¡ç†é¢æ¿ 邮件 > 邮件模版 设置邮件正文模版.', + ], + 'user' => [ + 'label' => '用户', + 'id' => 'ID', + 'username' => '用户å', + 'name' => 'å', + 'name_empty' => '匿åçš„', + 'surname' => 'å§“', + 'email' => '邮箱', + 'created_at' => '注册时间', + 'last_seen' => '上次登录时间', + 'is_guest' => '访客', + 'joined' => '加入', + 'is_online' => '当å‰åœ¨çº¿', + 'is_offline' => '当å‰ç¦»çº¿', + 'send_invite' => '用邮件å‘é€é‚€è¯·', + 'send_invite_comment' => 'å‘é€ä¸€ä¸ªåŒ…å«ç”¨æˆ·å和密ç çš„æ¬¢è¿Žæ¶ˆæ¯', + 'create_password' => '创建密ç ', + 'create_password_comment' => '输入登陆新密ç ', + 'reset_password' => 'é‡ç½®å¯†ç ', + 'reset_password_comment' => '请输入新密ç .', + 'confirm_password' => '确认密ç ', + 'confirm_password_comment' => '冿¬¡è¾“入密ç .', + 'groups' => '群组', + 'empty_groups' => 'æ— å¯ç”¨ç”¨æˆ·ç¾¤ç»„', + 'avatar' => '头åƒ', + 'details' => 'æè¿°', + 'account' => 'å¸å·', + 'block_mail' => '阻止å‘该用户å‘é€é‚®ä»¶', + 'status_guest' => '访客', + 'status_activated' => '活跃的', + 'status_registered' => '在册的', + ], + 'group' => [ + 'label' => '群组', + 'id' => 'ID', + 'name' => 'å§“å', + 'description_field' => 'æè¿°', + 'code' => 'ç¼–ç ', + 'code_comment' => 'è¾“å…¥ä¸€ä¸ªå”¯ä¸€ç¼–ç æ¥æ ‡å¿—当å‰ç”¨æˆ·ç»„', + 'created_at' => '创建', + 'users_count' => '用户', + ], + 'groups' => [ + 'menu_label' => '群组', + 'all_groups' => '用户群组', + 'new_group' => '新的用户组', + 'delete_selected_confirm' => '确定清空选中用户组么?', + 'list_title' => '管ç†ç¾¤ç»„', + 'delete_confirm' => '确定è¦åˆ é™¤è¯¥ç¾¤ç»„å—?', + 'delete_selected_success' => 'æˆåŠŸåˆ é™¤é€‰ä¸­çš„ç¾¤ç»„ã€‚', + 'delete_selected_empty' => '没有选中的è¦åˆ é™¤çš„群组。', + 'return_to_list' => '返回群组列表', + 'return_to_users' => '返回用户列表', + 'create_title' => '创建群组', + 'update_title' => '编辑群组', + 'preview_title' => '上一个群组', + ], + 'login' => [ + 'attribute_email' => '邮箱', + 'attribute_username' => '用户å', + ], + 'account' => [ + 'account' => 'å¸å·', + 'account_desc' => '用户信æ¯.', + 'redirect_to' => '跳转至', + 'redirect_to_desc' => '登录或注册æˆåŠŸåŽè·³è½¬é¡µé¢.', + 'code_param' => '激活ç å‚数。', + 'code_param_desc' => '激活ç çš„验è¯é¡µé¢URL傿•°', + 'invalid_user' => '未找到该用户。', + 'invalid_activation_code' => '错误的激活ç ', + 'invalid_deactivation_pass' => '密ç ä¸æ­£ç¡®ã€‚', + 'success_activation' => '您的å¸å·å·²æˆåŠŸæ¿€æ´».', + 'success_deactivation' => 'æˆåŠŸåœç”¨æ‚¨çš„è´¦å·ï¼Œå¾ˆæŠ±æ­‰çœ‹åˆ°æ‚¨ç¦»æˆ‘而去!', + 'success_saved' => '设置ä¿å­˜æˆåŠŸ!', + 'login_first' => '您需è¦å…ˆç™»å½•å¸å·æ‰èƒ½è®¿é—®è¯¥é¡µé¢!', + 'already_active' => '您的å¸å·æš‚未激活!', + 'activation_email_sent' => '激活邮件已å‘é€è‡³æ‚¨çš„邮箱.', + 'registration_disabled' => '当å‰å·²ç»ç¦ç”¨æ³¨å†Œã€‚', + 'sign_in' => '登录', + 'register' => '注册', + 'full_name' => 'å…¨å', + 'email' => '邮箱', + 'password' => '密ç ', + 'login' => '登录', + 'new_password' => '设置密ç ', + 'new_password_confirm' => '确认密ç ', + ], + 'reset_password' => [ + 'reset_password' => 'é‡ç½®å¯†ç ', + 'reset_password_desc' => '找回密ç .', + 'code_param' => 'é‡ç½®éªŒè¯ç å‚æ•°', + 'code_param_desc' => 'é‡ç½®å¯†ç çš„验è¯ç é¡µé¢URL傿•°', + ], + 'session' => [ + 'session' => '会è¯', + 'session_desc' => 'å°†ç”¨æˆ·ä¼šè¯æ·»åŠ åˆ°é¡µé¢ï¼Œå¯ä»¥é™åˆ¶é¡µè®¿é—®ã€‚', + 'security_title' => 'ä»…å…许', + 'security_desc' => 'è°å¯ä»¥è®¿é—®è¿™ä¸ªé¡µé¢ã€‚', + 'all' => '所有人', + 'users' => '注册用户', + 'guests' => '游客', + 'redirect_title' => '跳转至', + 'redirect_desc' => 'æ‹’ç»è®¿é—®æ—¶é‡å®šå‘到页é¢çš„å字。', + 'logout' => 'ä½ å·²ç»æˆåŠŸé€€å‡ºç™»é™†ï¼', + ], +]; \ No newline at end of file diff --git a/plugins/rainlab/user/lang/zh-tw/lang.php b/plugins/rainlab/user/lang/zh-tw/lang.php new file mode 100644 index 0000000..19973b9 --- /dev/null +++ b/plugins/rainlab/user/lang/zh-tw/lang.php @@ -0,0 +1,222 @@ + [ + 'name' => '會員', + 'description' => 'å‰å°æœƒå“¡ç®¡ç†ç³»çµ±ã€‚', + 'tab' => '會員', + 'access_users' => 'ç®¡ç†æœƒå“¡', + 'access_groups' => 'ç®¡ç†æœƒå“¡ç¾¤çµ„', + 'access_settings' => 'ç®¡ç†æœƒå“¡è¨­å®š', + 'impersonate_user' => '以指定會員登入', + ], + 'users' => [ + 'menu_label' => '會員', + 'all_users' => '所有會員', + 'new_user' => '新會員', + 'list_title' => 'ç®¡ç†æœƒå“¡', + 'trashed_hint_title' => '會員帳號已åœç”¨', + 'trashed_hint_desc' => '此會員已主動åœç”¨å¸³è™Ÿï¼Œä¸”䏿œƒåœ¨ç¶²ç«™ä¸Šå‡ºç¾ã€‚會員å¯éš¨æ™‚登入號以æ¢å¾©å…¶å¸³è™Ÿã€‚', + 'banned_hint_title' => '會員已å°éŽ–', + 'banned_hint_desc' => '此會員已被管ç†è€…å°éŽ–ï¼Œä¸”ä¸èƒ½å†æ¬¡ç™»å…¥ã€‚', + 'guest_hint_title' => 'éŠå®¢', + 'guest_hint_desc' => '此會員資料尚未註冊僅供åƒè€ƒã€‚', + 'activate_warning_title' => '帳號未啟用ï¼', + 'activate_warning_desc' => '此帳號尚未啟用,å¯èƒ½ç„¡æ³•登入。', + 'activate_confirm' => '是å¦å•Ÿç”¨æ­¤å¸³è™Ÿï¼Ÿ', + 'activated_success' => '帳號已啟用。', + 'activate_manually' => '手動啟用此帳號', + 'convert_guest_confirm' => '是å¦è½‰æ›éŠå®¢ç‚ºæ­£å¼æœƒå“¡ï¼Ÿ', + 'convert_guest_manually' => '轉æ›ç‚ºæ­£å¼æœƒå“¡', + 'convert_guest_success' => 'å¸³è™Ÿè½‰æ›æˆåŠŸã€‚', + 'impersonate_user' => '登入此會員', + 'impersonate_confirm' => '是å¦ä»¥æ­¤æœƒå“¡ç™»å…¥ï¼Ÿä½ å¯ä»¥ç™»å‡ºä»¥åˆ‡æ›ç‚ºåŽŸç‹€æ…‹ã€‚', + 'impersonate_success' => '你已模仿該會員登入。', + 'delete_confirm' => '是å¦åˆªé™¤æ­¤æœƒå“¡ï¼Ÿ', + 'unban_user' => '解除å°éŽ–æ­¤æœƒå“¡', + 'unban_confirm' => '是å¦è§£é™¤å°éŽ–æ­¤æœƒå“¡ï¼Ÿ', + 'unbanned_success' => '使用者已解除å°éŽ–ã€‚', + 'return_to_list' => '返回會員列表', + 'update_details' => '更新資訊', + 'bulk_actions' => '批次處ç†', + 'delete_selected' => '刪除é¸å–', + 'delete_selected_confirm' => '是å¦åˆªé™¤æ‰€é¸çš„æœƒå“¡ï¼Ÿ', + 'delete_selected_empty' => '沒有會員被é¸å–。', + 'delete_selected_success' => 'å·²æˆåŠŸåˆªé™¤æœƒå“¡ã€‚', + 'activate_selected' => '啟動帳號', + 'activate_selected_confirm' => '是å¦å•Ÿå‹•所é¸çš„帳號?', + 'activate_selected_empty' => '沒有會員被é¸å–。', + 'activate_selected_success' => 'å·²æˆåŠŸå•Ÿå‹•æœƒå“¡ã€‚', + 'deactivate_selected' => 'åœç”¨å¸³è™Ÿ', + 'deactivate_selected_confirm' => '是å¦åœç”¨æ‰€é¸çš„帳號?', + 'deactivate_selected_empty' => '沒有會員被é¸å–。', + 'deactivate_selected_success' => 'å·²æˆåŠŸåœç”¨å¸³è™Ÿã€‚', + 'restore_selected' => '復原帳號', + 'restore_selected_confirm' => '是å¦å¾©åŽŸæ‰€é¸çš„帳號?', + 'restore_selected_empty' => '沒有會員被é¸å–。', + 'restore_selected_success' => 'å·²æˆåŠŸå¾©åŽŸå¸³è™Ÿã€‚', + 'ban_selected' => 'å°éŽ–å¸³è™Ÿ', + 'ban_selected_confirm' => '是å¦å°éŽ–æ‰€é¸çš„帳號?', + 'ban_selected_empty' => '沒有會員被é¸å–。', + 'ban_selected_success' => 'å·²æˆåŠŸå°éŽ–å¸³è™Ÿã€‚', + 'unban_selected' => '解除å°éŽ–', + 'unban_selected_confirm' => '是å¦è§£é™¤å°éŽ–æ‰€é¸çš„帳號?', + 'unban_selected_empty' => '沒有會員被é¸å–。', + 'unban_selected_success' => 'å·²æˆåŠŸè§£é™¤å°éŽ–å¸³è™Ÿã€‚', + 'unsuspend' => '解除åœç”¨å¸³è™Ÿ', + 'unsuspend_success' => '帳號已解除åœç”¨ã€‚', + 'unsuspend_confirm' => '解除åœç”¨æ­¤å¸³è™Ÿï¼Ÿ', + ], + 'settings' => [ + 'users' => '會員', + 'menu_label' => '會員設定', + 'menu_description' => 'ç®¡ç†æœƒå“¡åŸºæœ¬è¨­å®šã€‚', + 'activation_tab' => '啟用', + 'signin_tab' => '登入', + 'registration_tab' => '註冊', + 'profile_tab' => '會員資料', + 'notifications_tab' => '通知', + 'allow_registration' => 'å…許會員註冊', + 'allow_registration_comment' => 'é—œé–‰æ­¤é …å°‡åªæœ‰ç®¡ç†å“¡èƒ½æ–°å¢žæœƒå“¡å¸³è™Ÿã€‚', + 'activate_mode' => '啟用模å¼', + 'activate_mode_comment' => '鏿“‡æœƒå“¡å¦‚何啟用帳號。', + 'activate_mode_auto' => '自動', + 'activate_mode_auto_comment' => '註冊後自動啟用。', + 'activate_mode_user' => '會員', + 'activate_mode_user_comment' => '會員使用電å­éƒµä»¶å•Ÿç”¨å¸³è™Ÿã€‚', + 'activate_mode_admin' => '管ç†å“¡', + 'activate_mode_admin_comment' => '僅管ç†å“¡å¯å•Ÿç”¨å¸³è™Ÿã€‚', + 'require_activation' => '需啟動後登入', + 'require_activation_comment' => '會員在首次登入å‰é ˆå…ˆå•Ÿå‹•帳號。', + 'use_throttle' => '節制嘗試登入', + 'use_throttle_comment' => 'é‡è¤‡ç™»å…¥å¤±æ•—將會暫時åœç”¨å¸³è™Ÿã€‚', + 'use_register_throttle' => '節制嘗試註冊', + 'use_register_throttle_comment' => '防止短期間內來自åŒå€‹ IP 的註冊請求。', + 'block_persistence' => 'ç¦æ­¢å¤šé‡ç™»å…¥', + 'block_persistence_comment' => '開啟後會員將無法在多個è£ç½®åŒæ™‚登入。', + 'login_attribute' => '登入帳號', + 'login_attribute_comment' => '鏿“‡æœƒå“¡ç™»å…¥æ‰€ä½¿ç”¨çš„帳號資料。', + 'remember_login' => 'ä¿ç•™ç™»å…¥ç‹€æ…‹', + 'remember_login_comment' => '鏿“‡æœƒå“¡ç™»å…¥ç‹€æ…‹æ˜¯å¦ä¿ç•™ã€‚', + 'remember_always' => '總是', + 'remember_never' => 'æ°¸ä¸', + 'remember_ask' => '會員登入時決定', + ], + 'user' => [ + 'label' => '會員', + 'id' => 'ID', + 'username' => '會員å稱', + 'name' => 'å', + 'name_empty' => 'Anonymous', + 'surname' => 'å§“', + 'email' => 'ä¿¡ç®±', + 'created_at' => '註冊日期', + 'last_seen' => '最後上線', + 'is_guest' => 'éŠå®¢', + 'joined' => '加入時間', + 'is_online' => '線上', + 'is_offline' => '已離線', + 'send_invite' => '寄é€é‚€è«‹å‡½', + 'send_invite_comment' => '寄é€ä¸€å°å«æœ‰å¸³è™Ÿå¯†ç¢¼çš„邀請函。', + 'create_password' => '設定密碼', + 'create_password_comment' => '請出入登入用密碼。', + 'reset_password' => 'é‡è¨­å¯†ç¢¼', + 'reset_password_comment' => '請輸入密碼以é‡è¨­ã€‚', + 'confirm_password' => '確èªå¯†ç¢¼', + 'confirm_password_comment' => 'è«‹é‡æ–°è¼¸å…¥å¯†ç¢¼ã€‚', + 'groups' => '群組', + 'empty_groups' => '尚無會員群組', + 'avatar' => 'é ­åƒ', + 'details' => '資訊', + 'account' => '帳號', + 'block_mail' => 'å–æ¶ˆæ‰€æœ‰å¯„é€è‡³æ­¤å¸³è™Ÿçš„郵件。', + 'status_guest' => 'éŠå®¢', + 'status_activated' => '已啟用', + 'status_registered' => '已註冊', + 'created_ip_address' => '註冊ä½ç½®', + 'last_ip_address' => '最後ä½ç½®', + ], + 'group' => [ + 'label' => '群組', + 'id' => 'ID', + 'name' => 'å稱', + 'description_field' => 'æè¿°', + 'code' => '代碼', + 'code_comment' => '輸入識別此群組用的唯一代碼。', + 'created_at' => '創建日期', + 'users_count' => '會員數', + ], + 'groups' => [ + 'menu_label' => '群組', + 'all_groups' => '會員群組', + 'new_group' => '新增群組', + 'delete_selected_confirm' => '是å¦åˆªé™¤æ‰€é¸çš„群組?', + 'list_title' => '管ç†ç¾¤çµ„', + 'delete_confirm' => '是å¦åˆªé™¤æ­¤ç¾¤çµ„?', + 'delete_selected_success' => 'å·²æˆåŠŸåˆªé™¤ç¾¤çµ„ã€‚', + 'delete_selected_empty' => '沒有會員被é¸å–。', + 'return_to_list' => '回到群組列表', + 'return_to_users' => '回到會員列表', + 'create_title' => '建立群組', + 'update_title' => '編輯群組', + 'preview_title' => 'é è¦½ç¾¤çµ„', + ], + 'login' => [ + 'attribute_email' => 'ä¿¡ç®±', + 'attribute_username' => '使用者å稱', + ], + 'account' => [ + 'account' => '帳號', + 'account_desc' => '會員管ç†è¡¨å–®ã€‚', + 'banned' => '很抱歉,此會員尚未啟動,請è¯ç¹«æˆ‘們以å–å¾—å”助。', + 'redirect_to' => '釿–°å°Žå‘', + 'redirect_to_desc' => 'æˆåŠŸç™»å…¥ã€æ›´æ–°æˆ–è¨»å†Šå¾Œé‡æ–°å°Žå‘çš„é é¢ã€‚', + 'code_param' => 'å•Ÿå‹•ç¢¼åƒæ•¸å稱', + 'code_param_desc' => '用於夾帶啟動碼的網å€åƒæ•¸å稱。', + 'force_secure' => '強制使用 HTTPS', + 'force_secure_desc' => '強制使用 HTTPS 釿–°å°Žå‘此網å€ã€‚', + 'invalid_user' => '帳號有誤。', + 'invalid_activation_code' => '啟動碼錯誤。', + 'invalid_deactivation_pass' => '您輸入的密碼有誤。', + 'invalid_current_pass' => '您輸入的密碼有誤。', + 'success_activation' => '已啟用您的帳號。', + 'success_deactivation' => 'å·²åœç”¨æ‚¨çš„帳號。', + 'success_saved' => '已儲存您的設定。', + 'login_first' => '請先登入您的帳號。', + 'already_active' => '您的帳號已啟動ï¼', + 'activation_email_sent' => '已寄é€å¸³è™Ÿå•Ÿå‹•信件至您的信箱。', + 'registration_disabled' => 'ç›®å‰æš«ä¸é–‹æ”¾è¨»å†Šã€‚', + 'registration_throttled' => '註冊狀態異常,請ç¨å¾Œé‡è©¦ã€‚', + 'sign_in' => '登入', + 'register' => '註冊', + 'full_name' => 'å…¨å', + 'email' => 'ä¿¡ç®±', + 'password' => '密碼', + 'login' => '登入', + 'new_password' => '新密碼', + 'new_password_confirm' => 'ç¢ºèªæ–°å¯†ç¢¼', + 'update_requires_password' => 'æ›´æ–°æ™‚è¦æ±‚密碼', + 'update_requires_password_comment' => '修改會員資料時須輸入目å‰çš„密碼。', + ], + 'reset_password' => [ + 'reset_password' => 'é‡è¨­å¯†ç¢¼', + 'reset_password_desc' => '忘記密碼表單。', + 'code_param' => 'é‡è¨­åƒæ•¸å稱', + 'code_param_desc' => '用於é‡è¨­å¯†ç¢¼çš„ç¶²å€åƒæ•¸å稱。', + ], + 'session' => [ + 'session' => '工作階段', + 'session_desc' => '工作階段å¯é™åˆ¶æœƒå“¡å­˜å–é é¢ã€‚', + 'security_title' => '僅å…許', + 'security_desc' => '誰å¯å­˜å–æ­¤é é¢ã€‚', + 'all' => '全部', + 'users' => '會員', + 'guests' => 'éŠå®¢', + 'allowed_groups_title' => 'å…許群組', + 'allowed_groups_description' => '鏿“‡å…許的群組,留白å…許全部。', + 'redirect_title' => '釿–°å°Žå‘', + 'redirect_desc' => '無法存å–çš„é é¢å°‡é‡æ–°å°Žå‘至所é¸çš„é é¢ã€‚', + 'logout' => '您已æˆåŠŸç™»å‡ºï¼', + 'stop_impersonate_success' => 'ä»¥åœæ­¢æ¨¡ä»¿è©²æœƒå“¡ç™»å…¥ç‹€æ…‹ã€‚', + ] +]; diff --git a/plugins/rainlab/user/models/MailBlocker.php b/plugins/rainlab/user/models/MailBlocker.php new file mode 100644 index 0000000..7ab3781 --- /dev/null +++ b/plugins/rainlab/user/models/MailBlocker.php @@ -0,0 +1,266 @@ + User::class + ]; + + /** + * @var array Templates names that cannot be blocked. + */ + protected static $safeTemplates = [ + 'rainlab.user::mail.restore' + ]; + + /** + * Sets mail blocking preferences for a user. Eg: + * + * MailBlocker::setPreferences($user, [acme.blog::post.new_reply => 0]) + * + * MailBlocker::setPreferences($user, [acme.blog::post.new_reply => 0], [fillable => [acme.blog::post.new_reply]]) + * + * MailBlocker::setPreferences($user, [template_alias => 0], [aliases => [template_alias => acme.blog::post.new_reply]]) + * + * Supported options: + * - aliases: Alias definitions, with alias as key and template as value. + * - fillable: An array of expected templates, undefined templates are ignored. + * - verify: Only allow mail templates that are registered in the system. + * + * @param array $templates Template name as key and boolean as value. If false, template is blocked. + * @param RainLab\User\Models\User $user + * @param array $options + * @return void + */ + public static function setPreferences($user, $templates, $options = []) + { + $templates = (array) $templates; + + if (!$user) { + throw new Exception('A user must be provided for MailBlocker::setPreferences'); + } + + extract(array_merge([ + 'aliases' => [], + 'fillable' => [], + 'verify' => false, + ], $options)); + + if ($aliases) { + $fillable = array_merge($fillable, array_values($aliases)); + $templates = array_build($templates, function($key, $value) use ($aliases) { + return [array_get($aliases, $key, $key), $value]; + }); + } + + if ($fillable) { + $templates = array_intersect_key($templates, array_flip($fillable)); + } + + if ($verify) { + $existing = MailTemplate::listAllTemplates(); + $templates = array_intersect_key($templates, $existing); + } + + $currentBlocks = array_flip(static::checkAllForUser($user)); + foreach ($templates as $template => $value) { + // User wants to receive mail and is blocking + if ($value && isset($currentBlocks[$template])) { + static::removeBlock($template, $user); + } + // User does not want to receive mail and not blocking + elseif (!$value && !isset($currentBlocks[$template])) { + static::addBlock($template, $user); + } + } + } + + /** + * Adds a block for a user and a mail view/template code. + * @param string $template + * @param RainLab\User\Models\User $user + * @return bool + */ + public static function addBlock($template, $user) + { + $blocker = static::where([ + 'template' => $template, + 'user_id' => $user->id + ])->first(); + + if ($blocker && $blocker->email == $user->email) { + return false; + } + + if (!$blocker) { + $blocker = new static; + $blocker->template = $template; + $blocker->user_id = $user->id; + } + + $blocker->email = $user->email; + $blocker->save(); + + return true; + } + + /** + * Removes a block for a user and a mail view/template code. + * @param string $template + * @param RainLab\User\Models\User $user + * @return bool + */ + public static function removeBlock($template, $user) + { + $blocker = static::where([ + 'template' => $template, + 'user_id' => $user->id + ])->orWhere(function ($query) use ($template, $user) { + $query->where([ + 'template' => $template, + 'email' => $user->email + ]); + })->get(); + + if (!$blocker->count()) { + return false; + } + + $blocker->each(function($block) { + $block->delete(); + }); + + return true; + } + + /** + * Blocks all mail messages for a user. + * @param RainLab\User\Models\User $user + * @return bool + */ + public static function blockAll($user) + { + return static::addBlock('*', $user); + } + + /** + * Removes block on all mail messages for a user. + * @param RainLab\User\Models\User $user + * @return bool + */ + public static function unblockAll($user) + { + return static::removeBlock('*', $user); + } + + /** + * Checks if a user is blocking all templates. + * @param RainLab\User\Models\User $user + * @return bool + */ + public static function isBlockAll($user) + { + return count(static::checkForEmail('*', $user->email)) > 0; + } + + /** + * Updates mail blockers for a user if they change their email address + * @param Model $user + * @return mixed + */ + public static function syncUser($user) + { + return static::where('user_id', $user->id)->update(['email' => $user->email]); + } + + /** + * Returns a list of mail templates blocked by the user. + * @param Model $user + * @return array + */ + public static function checkAllForUser($user) + { + return static::where('user_id', $user->id)->lists('template'); + } + + /** + * Checks if an email address has blocked a given template, + * returns an array of blocked emails. + * @param string $template + * @param string $email + * @return array + */ + public static function checkForEmail($template, $email) + { + if (in_array($template, static::$safeTemplates)) { + return []; + } + + if (empty($email)) { + return []; + } + + if (!is_array($email)) { + $email = [$email => null]; + } + + $emails = array_keys($email); + + return static::where(function($q) use ($template) { + $q->where('template', $template)->orWhere('template', '*'); + }) + ->whereIn('email', $emails) + ->lists('email'); + } + + /** + * Filters a Illuminate\Mail\Message and removes blocked recipients. + * If no recipients remain, false is returned. Returns null if mailing + * should proceed. + * @param string $template + * @param Illuminate\Mail\Message $message + * @return bool|null + */ + public static function filterMessage($template, $message) + { + $recipients = $message->getTo(); + $blockedAddresses = static::checkForEmail($template, $recipients); + + if (!count($blockedAddresses)) { + return null; + } + + foreach ($recipients as $address => $name) { + if (in_array($address, $blockedAddresses)) { + unset($recipients[$address]); + } + } + + $message->setTo($recipients); + return count($recipients) ? null : false; + } +} diff --git a/plugins/rainlab/user/models/Settings.php b/plugins/rainlab/user/models/Settings.php new file mode 100644 index 0000000..7355168 --- /dev/null +++ b/plugins/rainlab/user/models/Settings.php @@ -0,0 +1,99 @@ +require_activation = config('rainlab.user::requireActivation', true); + $this->activate_mode = config('rainlab.user::activateMode', self::ACTIVATE_AUTO); + $this->use_throttle = config('rainlab.user::useThrottle', true); + $this->block_persistence = config('rainlab.user::blockPersistence', false); + $this->allow_registration = config('rainlab.user::allowRegistration', true); + $this->login_attribute = config('rainlab.user::loginAttribute', self::LOGIN_EMAIL); + $this->remember_login = config('rainlab.user::rememberLogin', self::REMEMBER_ALWAYS); + $this->use_register_throttle = config('rainlab.user::useRegisterThrottle', true); + } + + public function getActivateModeOptions() + { + return [ + self::ACTIVATE_AUTO => [ + 'rainlab.user::lang.settings.activate_mode_auto', + 'rainlab.user::lang.settings.activate_mode_auto_comment' + ], + self::ACTIVATE_USER => [ + 'rainlab.user::lang.settings.activate_mode_user', + 'rainlab.user::lang.settings.activate_mode_user_comment' + ], + self::ACTIVATE_ADMIN => [ + 'rainlab.user::lang.settings.activate_mode_admin', + 'rainlab.user::lang.settings.activate_mode_admin_comment' + ] + ]; + } + + public function getActivateModeAttribute($value) + { + if (!$value) { + return self::ACTIVATE_AUTO; + } + + return $value; + } + + public function getLoginAttributeOptions() + { + return [ + self::LOGIN_EMAIL => ['rainlab.user::lang.login.attribute_email'], + self::LOGIN_USERNAME => ['rainlab.user::lang.login.attribute_username'] + ]; + } + + public function getRememberLoginOptions() + { + return [ + self::REMEMBER_ALWAYS => [ + 'rainlab.user::lang.settings.remember_always', + ], + self::REMEMBER_NEVER => [ + 'rainlab.user::lang.settings.remember_never', + ], + self::REMEMBER_ASK => [ + 'rainlab.user::lang.settings.remember_ask', + ] + ]; + } + + public function getRememberLoginAttribute($value) + { + if (!$value) { + return self::REMEMBER_ALWAYS; + } + + return $value; + } +} diff --git a/plugins/rainlab/user/models/Throttle.php b/plugins/rainlab/user/models/Throttle.php new file mode 100644 index 0000000..d9b4916 --- /dev/null +++ b/plugins/rainlab/user/models/Throttle.php @@ -0,0 +1,18 @@ + User::class + ]; +} diff --git a/plugins/rainlab/user/models/User.php b/plugins/rainlab/user/models/User.php new file mode 100644 index 0000000..bef0409 --- /dev/null +++ b/plugins/rainlab/user/models/User.php @@ -0,0 +1,544 @@ + 'required|between:6,255|email|unique:users', + 'avatar' => 'nullable|image|max:4000', + 'username' => 'required|between:2,255|unique:users', + 'password' => 'required:create|between:8,255|confirmed', + 'password_confirmation' => 'required_with:password|between:8,255', + ]; + + /** + * @var array Relations + */ + public $belongsToMany = [ + 'groups' => [UserGroup::class, 'table' => 'users_groups'] + ]; + + public $attachOne = [ + 'avatar' => \System\Models\File::class + ]; + + /** + * @var array The attributes that are mass assignable. + */ + protected $fillable = [ + 'name', + 'surname', + 'login', + 'username', + 'email', + // + 'middle_name', + 'date_birth', + 'passport', + 'place_passport', + 'address_residence', + 'mobile_phone', + 'home_phone', + // + 'password', + 'password_confirmation', + 'created_ip_address', + 'last_ip_address' + ]; + + /** + * Reset guarded fields, because we use $fillable instead. + * @var array The attributes that aren't mass assignable. + */ + protected $guarded = ['*']; + + /** + * Purge attributes from data set. + */ + protected $purgeable = ['password_confirmation', 'send_invite']; + + protected $dates = [ + 'last_seen', + 'deleted_at', + 'created_at', + 'updated_at', + 'activated_at', + 'last_login' + ]; + + public static $loginAttribute = null; + + /** + * Sends the confirmation email to a user, after activating. + * @param string $code + * @return bool + */ + public function attemptActivation($code) + { + if ($this->trashed()) { + if ($code === $this->activation_code) { + $this->restore(); + } else { + return false; + } + } else { + $result = parent::attemptActivation($code); + + if ($result === false) { + return false; + } + } + + Event::fire('rainlab.user.activate', [$this]); + + return true; + } + + /** + * Converts a guest user to a registered one and sends an invitation notification. + * @return void + */ + public function convertToRegistered($sendNotification = true) + { + // Already a registered user + if (!$this->is_guest) { + return; + } + + if ($sendNotification) { + $this->generatePassword(); + } + + $this->is_guest = false; + $this->save(); + + if ($sendNotification) { + $this->sendInvitation(); + } + } + + // + // Constructors + // + + /** + * Looks up a user by their email address. + * @return self + */ + public static function findByEmail($email) + { + if (!$email) { + return; + } + + return self::where('email', $email)->first(); + } + + // + // Getters + // + + /** + * clearPersistCode will forcibly sign the user out + */ + public function clearPersistCode() + { + $this->persist_code = null; + $this->timestamps = false; + $this->save(); + } + + /** + * Gets a code for when the user is persisted to a cookie or session which identifies the user. + * @return string + */ + public function getPersistCode() + { + $block = UserSettings::get('block_persistence', false); + + if ($block || !$this->persist_code) { + return parent::getPersistCode(); + } + + return $this->persist_code; + } + + /** + * Returns the public image file path to this user's avatar. + */ + public function getAvatarThumb($size = 25, $options = null) + { + if (is_string($options)) { + $options = ['default' => $options]; + } + elseif (!is_array($options)) { + $options = []; + } + + // Default is "mm" (Mystery man) + $default = array_get($options, 'default', 'mm'); + + if ($this->avatar) { + return $this->avatar->getThumb($size, $size, $options); + } + else { + return '//www.gravatar.com/avatar/'. + md5(strtolower(trim($this->email))). + '?s='.$size. + '&d='.urlencode($default); + } + } + + /** + * Returns the name for the user's login. + * @return string + */ + public function getLoginName() + { + if (static::$loginAttribute !== null) { + return static::$loginAttribute; + } + + return static::$loginAttribute = UserSettings::get('login_attribute', UserSettings::LOGIN_EMAIL); + } + + /** + * Returns the minimum length for a new password from settings. + * @return int + */ + public static function getMinPasswordLength() + { + return Config::get('rainlab.user::minPasswordLength', 8); + } + + // + // Scopes + // + + public function scopeIsActivated($query) + { + return $query->where('is_activated', 1); + } + + public function scopeFilterByGroup($query, $filter) + { + return $query->whereHas('groups', function($group) use ($filter) { + $group->whereIn('id', $filter); + }); + } + + // + // Events + // + + /** + * Before validation event + * @return void + */ + public function beforeValidate() + { + /* + * Guests are special + */ + if ($this->is_guest && !$this->password) { + $this->generatePassword(); + } + + /* + * When the username is not used, the email is substituted. + */ + if ( + (!$this->username) || + ($this->isDirty('email') && $this->getOriginal('email') == $this->username) + ) { + $this->username = $this->email; + } + + /* + * Apply Password Length Settings + */ + $minPasswordLength = static::getMinPasswordLength(); + $this->rules['password'] = "required:create|between:$minPasswordLength,255|confirmed"; + $this->rules['password_confirmation'] = "required_with:password|between:$minPasswordLength,255"; + } + + /** + * After create event + * @return void + */ + public function afterCreate() + { + $this->restorePurgedValues(); + + if ($this->send_invite) { + $this->sendInvitation(); + } + } + + /** + * Before login event + * @return void + */ + public function beforeLogin() + { + if ($this->is_guest) { + $login = $this->getLogin(); + throw new AuthException(sprintf( + 'Cannot login user "%s" as they are not registered.', $login + )); + } + + parent::beforeLogin(); + } + + /** + * After login event + * @return void + */ + public function afterLogin() + { + $this->last_login = $this->freshTimestamp(); + + if ($this->trashed()) { + $this->restore(); + + Mail::sendTo($this, 'rainlab.user::mail.reactivate', [ + 'name' => $this->name + ]); + + Event::fire('rainlab.user.reactivate', [$this]); + } + else { + parent::afterLogin(); + } + + Event::fire('rainlab.user.login', [$this]); + } + + /** + * After delete event + * @return void + */ + public function afterDelete() + { + if ($this->isSoftDelete()) { + Event::fire('rainlab.user.deactivate', [$this]); + return; + } + + $this->avatar && $this->avatar->delete(); + + parent::afterDelete(); + } + + // + // Banning + // + + /** + * Ban this user, preventing them from signing in. + * @return void + */ + public function ban() + { + Auth::findThrottleByUserId($this->id)->ban(); + } + + /** + * Remove the ban on this user. + * @return void + */ + public function unban() + { + Auth::findThrottleByUserId($this->id)->unban(); + } + + /** + * Check if the user is banned. + * @return bool + */ + public function isBanned() + { + $throttle = Auth::createThrottleModel()->where('user_id', $this->id)->first(); + return $throttle ? $throttle->is_banned : false; + } + + // + // Suspending + // + + /** + * Check if the user is suspended. + * @return bool + */ + public function isSuspended() + { + return Auth::findThrottleByUserId($this->id)->checkSuspended(); + } + + /** + * Remove the suspension on this user. + * @return void + */ + public function unsuspend() + { + Auth::findThrottleByUserId($this->id)->unsuspend(); + } + + // + // IP Recording and Throttle + // + + /** + * Records the last_ip_address to reflect the last known IP for this user. + * @param string|null $ipAddress + * @return void + */ + public function touchIpAddress($ipAddress) + { + $this + ->newQuery() + ->where('id', $this->id) + ->update(['last_ip_address' => $ipAddress]) + ; + } + + /** + * Returns true if IP address is throttled and cannot register + * again. Maximum 3 registrations every 60 minutes. + * @param string|null $ipAddress + * @return bool + */ + public static function isRegisterThrottled($ipAddress) + { + if (!$ipAddress) { + return false; + } + + $timeLimit = Carbon::now()->subMinutes(60); + $count = static::make() + ->where('created_ip_address', $ipAddress) + ->where('created_at', '>', $timeLimit) + ->count() + ; + + return $count > 2; + } + + // + // Last Seen + // + + /** + * Checks if the user has been seen in the last 5 minutes, and if not, + * updates the last_seen timestamp to reflect their online status. + * @return void + */ + public function touchLastSeen() + { + if ($this->isOnline()) { + return; + } + + $oldTimestamps = $this->timestamps; + $this->timestamps = false; + + $this + ->newQuery() + ->where('id', $this->id) + ->update(['last_seen' => $this->freshTimestamp()]) + ; + + $this->last_seen = $this->freshTimestamp(); + $this->timestamps = $oldTimestamps; + } + + /** + * Returns true if the user has been active within the last 5 minutes. + * @return bool + */ + public function isOnline() + { + if (!$this->last_seen) { + return false; + } + + return $this->last_seen > $this->freshTimestamp()->subMinutes(5); + } + + /** + * Returns the date this user was last seen. + * @deprecated use last_seen attribute + * @return Carbon\Carbon + */ + public function getLastSeen() + { + return $this->last_seen ?: $this->created_at; + } + + // + // Utils + // + + /** + * Returns the variables available when sending a user notification. + * @return array + */ + public function getNotificationVars() + { + $vars = [ + 'name' => $this->name, + 'email' => $this->email, + 'username' => $this->username, + 'login' => $this->getLogin(), + 'password' => $this->getOriginalHashValue('password') + ]; + + /* + * Extensibility + */ + $result = Event::fire('rainlab.user.getNotificationVars', [$this]); + if ($result && is_array($result)) { + $vars = call_user_func_array('array_merge', $result) + $vars; + } + + return $vars; + } + + /** + * Sends an invitation to the user using template "rainlab.user::mail.invite". + * @return void + */ + protected function sendInvitation() + { + Mail::sendTo($this, 'rainlab.user::mail.invite', $this->getNotificationVars()); + } + + /** + * Assigns this user with a random password. + * @return void + */ + protected function generatePassword() + { + $this->password = $this->password_confirmation = Str::random(static::getMinPasswordLength()); + } +} diff --git a/plugins/rainlab/user/models/UserGroup.php b/plugins/rainlab/user/models/UserGroup.php new file mode 100644 index 0000000..20496a4 --- /dev/null +++ b/plugins/rainlab/user/models/UserGroup.php @@ -0,0 +1,60 @@ + 'required|between:3,64', + 'code' => 'required|regex:/^[a-zA-Z0-9_\-]+$/|unique:user_groups', + ]; + + /** + * @var array Relations + */ + public $belongsToMany = [ + 'users' => [User::class, 'table' => 'users_groups'], + 'users_count' => [User::class, 'table' => 'users_groups', 'count' => true] + ]; + + /** + * @var array The attributes that are mass assignable. + */ + protected $fillable = [ + 'name', + 'code', + 'description' + ]; + + protected static $guestGroup = null; + + /** + * Returns the guest user group. + * @return RainLab\User\Models\UserGroup + */ + public static function getGuestGroup() + { + if (self::$guestGroup !== null) { + return self::$guestGroup; + } + + $group = self::where('code', self::GROUP_GUEST)->first() ?: false; + + return self::$guestGroup = $group; + } +} diff --git a/plugins/rainlab/user/models/settings/fields.yaml b/plugins/rainlab/user/models/settings/fields.yaml new file mode 100644 index 0000000..c01016c --- /dev/null +++ b/plugins/rainlab/user/models/settings/fields.yaml @@ -0,0 +1,69 @@ +# =================================== +# Field Definitions +# =================================== + +tabs: + fields: + # Throttle Sign In + use_throttle: + span: left + label: rainlab.user::lang.settings.use_throttle + comment: rainlab.user::lang.settings.use_throttle_comment + type: switch + tab: rainlab.user::lang.settings.signin_tab + + # Prevent concurrent sessions + block_persistence: + span: right + label: rainlab.user::lang.settings.block_persistence + comment: rainlab.user::lang.settings.block_persistence_comment + type: switch + tab: rainlab.user::lang.settings.signin_tab + + # Login Attribute + login_attribute: + span: left + label: rainlab.user::lang.settings.login_attribute + commentAbove: rainlab.user::lang.settings.login_attribute_comment + type: radio + tab: rainlab.user::lang.settings.signin_tab + + # Remeber Login Mode + remember_login: + span: right + label: rainlab.user::lang.settings.remember_login + commentAbove: rainlab.user::lang.settings.remember_login_comment + type: radio + tab: rainlab.user::lang.settings.signin_tab + + # Require Activation + allow_registration: + span: left + label: rainlab.user::lang.settings.allow_registration + comment: rainlab.user::lang.settings.allow_registration_comment + type: switch + tab: rainlab.user::lang.settings.registration_tab + + # Enable registration throttling + use_register_throttle: + span: right + label: rainlab.user::lang.settings.use_register_throttle + comment: rainlab.user::lang.settings.use_register_throttle_comment + type: switch + tab: rainlab.user::lang.settings.registration_tab + + # Require Activation + require_activation: + span: left + label: rainlab.user::lang.settings.require_activation + comment: rainlab.user::lang.settings.require_activation_comment + type: switch + tab: rainlab.user::lang.settings.activation_tab + + # Activation Mode + activate_mode: + span: left + commentAbove: rainlab.user::lang.settings.activate_mode_comment + label: rainlab.user::lang.settings.activate_mode + type: radio + tab: rainlab.user::lang.settings.activation_tab diff --git a/plugins/rainlab/user/models/user/columns.yaml b/plugins/rainlab/user/models/user/columns.yaml new file mode 100644 index 0000000..f3c27be --- /dev/null +++ b/plugins/rainlab/user/models/user/columns.yaml @@ -0,0 +1,50 @@ +# =================================== +# Column Definitions +# =================================== + +columns: + + id: + label: rainlab.user::lang.user.id + invisible: true + + username: + label: rainlab.user::lang.user.username + searchable: true + invisible: true + + name: + label: rainlab.user::lang.user.name + searchable: true + + surname: + label: rainlab.user::lang.user.surname + searchable: true + invisible: true + + email: + label: rainlab.user::lang.user.email + searchable: true + + created_at: + label: rainlab.user::lang.user.created_at + type: timetense + + last_seen: + label: rainlab.user::lang.user.last_seen + type: timetense + + is_guest: + label: rainlab.user::lang.user.is_guest + type: switch + invisible: true + + created_ip_address: + label: rainlab.user::lang.user.created_ip_address + searchable: true + invisible: true + + last_ip_address: + label: rainlab.user::lang.user.last_ip_address + searchable: true + invisible: true diff --git a/plugins/rainlab/user/models/user/fields.yaml b/plugins/rainlab/user/models/user/fields.yaml new file mode 100644 index 0000000..953496c --- /dev/null +++ b/plugins/rainlab/user/models/user/fields.yaml @@ -0,0 +1,113 @@ +fields: + name: + label: 'rainlab.user::lang.user.name' + span: auto + type: text + surname: + label: 'rainlab.user::lang.user.surname' + span: auto + type: text + middle_name: + label: 'Middle name' + span: left + type: text + date_birth: + label: 'Date of Birth' + span: auto + type: text + passport: + label: 'Passport Series' + span: left + type: text + place_passport: + label: 'Place of issue of the passport' + span: right + type: text + address_residence: + label: 'Address of residence' + span: left + type: text + mobile_phone: + label: 'Mobile phone' + span: right + type: text + home_phone: + label: 'Home phone' + span: left + type: text +tabs: + fields: + email: + label: 'rainlab.user::lang.user.email' + tab: 'rainlab.user::lang.user.account' + span: full + type: text + send_invite: + type: checkbox + label: 'rainlab.user::lang.user.send_invite' + comment: 'rainlab.user::lang.user.send_invite_comment' + tab: 'rainlab.user::lang.user.account' + default: true + context: create + block_mail: + label: 'rainlab.user::lang.user.block_mail' + tab: 'rainlab.user::lang.user.account' + type: checkbox + span: full + cssClass: field-align-above + context: update + password@create: + label: 'rainlab.user::lang.user.create_password' + comment: 'rainlab.user::lang.user.create_password_comment' + tab: 'rainlab.user::lang.user.account' + type: password + span: left + password@update: + label: 'rainlab.user::lang.user.reset_password' + comment: 'rainlab.user::lang.user.reset_password_comment' + tab: 'rainlab.user::lang.user.account' + type: password + span: left + password_confirmation: + label: 'rainlab.user::lang.user.confirm_password' + comment: 'rainlab.user::lang.user.confirm_password_comment' + tab: 'rainlab.user::lang.user.account' + type: password + span: right + context: + - create + - update + username: + label: 'rainlab.user::lang.user.username' + tab: 'rainlab.user::lang.user.account' + hidden: true + span: left + type: text + groups: + label: 'rainlab.user::lang.user.groups' + tab: 'rainlab.user::lang.user.account' + type: relation + emptyOption: 'rainlab.user::lang.user.empty_groups' + created_ip_address: + label: 'rainlab.user::lang.user.created_ip_address' + span: auto + disabled: true + tab: 'rainlab.user::lang.user.account' + context: preview + type: text + last_ip_address: + label: 'rainlab.user::lang.user.last_ip_address' + span: auto + disabled: true + tab: 'rainlab.user::lang.user.account' + context: preview + type: text +secondaryTabs: + fields: + avatar: + label: 'rainlab.user::lang.user.avatar' + type: fileupload + mode: image + imageHeight: 260 + imageWidth: 260 + tab: Misc diff --git a/plugins/rainlab/user/models/usergroup/columns.yaml b/plugins/rainlab/user/models/usergroup/columns.yaml new file mode 100644 index 0000000..441a7fd --- /dev/null +++ b/plugins/rainlab/user/models/usergroup/columns.yaml @@ -0,0 +1,26 @@ +# =================================== +# Column Definitions +# =================================== + +columns: + + id: + label: rainlab.user::lang.group.id + invisible: true + + name: + label: rainlab.user::lang.group.name + searchable: true + + code: + label: rainlab.user::lang.group.code + + created_at: + label: rainlab.user::lang.group.created_at + + users_count: + label: rainlab.user::lang.group.users_count + relation: users_count + valueFrom: count + default: 0 + sortable: false diff --git a/plugins/rainlab/user/models/usergroup/fields.yaml b/plugins/rainlab/user/models/usergroup/fields.yaml new file mode 100644 index 0000000..4a3da10 --- /dev/null +++ b/plugins/rainlab/user/models/usergroup/fields.yaml @@ -0,0 +1,19 @@ +# =================================== +# Field Definitions +# =================================== + +fields: + name: + label: rainlab.user::lang.group.name + span: left + + code: + label: rainlab.user::lang.group.code + comment: rainlab.user::lang.group.code_comment + span: right + preset: name + + description: + label: rainlab.user::lang.group.description_field + type: textarea + size: tiny diff --git a/plugins/rainlab/user/notifyrules/UserActivatedEvent.php b/plugins/rainlab/user/notifyrules/UserActivatedEvent.php new file mode 100644 index 0000000..5c3b3f4 --- /dev/null +++ b/plugins/rainlab/user/notifyrules/UserActivatedEvent.php @@ -0,0 +1,18 @@ + 'Activated', + 'description' => 'A user is activated', + 'group' => 'user' + ]; + } +} diff --git a/plugins/rainlab/user/notifyrules/UserAttributeCondition.php b/plugins/rainlab/user/notifyrules/UserAttributeCondition.php new file mode 100644 index 0000000..94a99b3 --- /dev/null +++ b/plugins/rainlab/user/notifyrules/UserAttributeCondition.php @@ -0,0 +1,37 @@ +host; + + $attribute = $hostObj->subcondition; + + if (!$user = array_get($params, 'user')) { + throw new ApplicationException('Error evaluating the user attribute condition: the user object is not found in the condition parameters.'); + } + + return parent::evalIsTrue($user); + } +} diff --git a/plugins/rainlab/user/notifyrules/UserRegisteredEvent.php b/plugins/rainlab/user/notifyrules/UserRegisteredEvent.php new file mode 100644 index 0000000..1aeeab2 --- /dev/null +++ b/plugins/rainlab/user/notifyrules/UserRegisteredEvent.php @@ -0,0 +1,18 @@ + 'Registered', + 'description' => 'A user has registered', + 'group' => 'user' + ]; + } +} diff --git a/plugins/rainlab/user/notifyrules/userattributecondition/attributes.yaml b/plugins/rainlab/user/notifyrules/userattributecondition/attributes.yaml new file mode 100644 index 0000000..2f4c894 --- /dev/null +++ b/plugins/rainlab/user/notifyrules/userattributecondition/attributes.yaml @@ -0,0 +1,17 @@ +# =================================== +# Condition Attribute Definitions +# =================================== + +attributes: + + name: + label: Name + + surname: + label: Surname + + username: + label: Login / Username + + email: + label: Email address diff --git a/plugins/rainlab/user/phpunit.xml b/plugins/rainlab/user/phpunit.xml new file mode 100644 index 0000000..fd0c351 --- /dev/null +++ b/plugins/rainlab/user/phpunit.xml @@ -0,0 +1,42 @@ + + + + + ./tests + + + + + + + + + + + + + ./classes + ./components + ./controllers + ./facades + ./models + ./notifyrules + + + ./Plugin.php + ./tests + ./updates + ./vendor + + + diff --git a/plugins/rainlab/user/tests/UserPluginTestCase.php b/plugins/rainlab/user/tests/UserPluginTestCase.php new file mode 100644 index 0000000..9237b85 --- /dev/null +++ b/plugins/rainlab/user/tests/UserPluginTestCase.php @@ -0,0 +1,34 @@ +logout(); + + // Register the auth facade + $alias = AliasLoader::getInstance(); + $alias->alias('Auth', \RainLab\User\Facades\Auth::class); + + App::singleton('user.auth', function () { + return \RainLab\User\Classes\AuthManager::instance(); + }); + } +} diff --git a/plugins/rainlab/user/tests/unit/facades/AuthFacadeTest.php b/plugins/rainlab/user/tests/unit/facades/AuthFacadeTest.php new file mode 100644 index 0000000..8e0995b --- /dev/null +++ b/plugins/rainlab/user/tests/unit/facades/AuthFacadeTest.php @@ -0,0 +1,74 @@ + 'Some User', + 'email' => 'some@website.tld', + 'password' => 'changeme', + 'password_confirmation' => 'changeme', + ]); + + $this->assertEquals(1, User::count()); + $this->assertInstanceOf(\RainLab\User\Models\User::class, $user); + + $this->assertFalse($user->is_activated); + $this->assertEquals('Some User', $user->name); + $this->assertEquals('some@website.tld', $user->email); + } + + public function testRegisterUserWithAutoActivation() + { + // Stop activation events from other plugins + Event::forget('rainlab.user.activate'); + + $user = Auth::register([ + 'name' => 'Some User', + 'email' => 'some@website.tld', + 'password' => 'changeme', + 'password_confirmation' => 'changeme', + ], true); + + $this->assertTrue($user->is_activated); + + $this->assertTrue(Auth::check()); + } + + public function testRegisterGuest() + { + $guest = Auth::registerGuest(['email' => 'person@acme.tld']); + + $this->assertEquals(1, User::count()); + $this->assertInstanceOf(\RainLab\User\Models\User::class, $guest); + + $this->assertTrue($guest->is_guest); + $this->assertEquals('person@acme.tld', $guest->email); + } + + public function testLoginAndCheckAuth() + { + $this->assertFalse(Auth::check()); + + $user = User::create([ + 'name' => 'Some User', + 'email' => 'some@website.tld', + 'password' => 'changeme', + 'password_confirmation' => 'changeme', + ]); + + $user->is_activated = true; + $user->activated_at = now(); + $user->save(); + + Auth::login($user); + + $this->assertTrue(Auth::check()); + } +} diff --git a/plugins/rainlab/user/updates/create_mail_blockers_table.php b/plugins/rainlab/user/updates/create_mail_blockers_table.php new file mode 100644 index 0000000..043a525 --- /dev/null +++ b/plugins/rainlab/user/updates/create_mail_blockers_table.php @@ -0,0 +1,27 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->string('email')->index()->nullable(); + $table->string('template')->index()->nullable(); + $table->integer('user_id')->unsigned()->nullable()->index(); + $table->timestamps(); + }); + } + + public function down() + { + Schema::dropIfExists('rainlab_user_mail_blockers'); + } + +} diff --git a/plugins/rainlab/user/updates/create_throttle_table.php b/plugins/rainlab/user/updates/create_throttle_table.php new file mode 100644 index 0000000..339ae01 --- /dev/null +++ b/plugins/rainlab/user/updates/create_throttle_table.php @@ -0,0 +1,31 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->integer('user_id')->unsigned()->nullable()->index(); + $table->string('ip_address')->nullable()->index(); + $table->integer('attempts')->default(0); + $table->timestamp('last_attempt_at')->nullable(); + $table->boolean('is_suspended')->default(0); + $table->timestamp('suspended_at')->nullable(); + $table->boolean('is_banned')->default(0); + $table->timestamp('banned_at')->nullable(); + }); + } + + public function down() + { + Schema::dropIfExists('user_throttle'); + } + +} diff --git a/plugins/rainlab/user/updates/create_user_groups_table.php b/plugins/rainlab/user/updates/create_user_groups_table.php new file mode 100644 index 0000000..83884f4 --- /dev/null +++ b/plugins/rainlab/user/updates/create_user_groups_table.php @@ -0,0 +1,36 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->string('name'); + $table->string('code')->nullable()->index(); + $table->text('description')->nullable(); + $table->timestamps(); + }); + + Schema::create('users_groups', function($table) + { + $table->engine = 'InnoDB'; + $table->integer('user_id')->unsigned(); + $table->integer('user_group_id')->unsigned(); + $table->primary(['user_id', 'user_group_id'], 'rainlab_user_group'); + }); + } + + public function down() + { + Schema::dropIfExists('user_groups'); + Schema::dropIfExists('users_groups'); + } + +} diff --git a/plugins/rainlab/user/updates/create_users_table.php b/plugins/rainlab/user/updates/create_users_table.php new file mode 100644 index 0000000..39f0aa3 --- /dev/null +++ b/plugins/rainlab/user/updates/create_users_table.php @@ -0,0 +1,34 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->string('name')->nullable(); + $table->string('email')->unique(); + $table->string('password'); + $table->string('activation_code')->nullable()->index(); + $table->string('persist_code')->nullable(); + $table->string('reset_password_code')->nullable()->index(); + $table->text('permissions')->nullable(); + $table->boolean('is_activated')->default(0); + $table->timestamp('activated_at')->nullable(); + $table->timestamp('last_login')->nullable(); + $table->timestamps(); + }); + } + + public function down() + { + Schema::dropIfExists('users'); + } + +} diff --git a/plugins/rainlab/user/updates/seed_user_groups_table.php b/plugins/rainlab/user/updates/seed_user_groups_table.php new file mode 100644 index 0000000..cce04fa --- /dev/null +++ b/plugins/rainlab/user/updates/seed_user_groups_table.php @@ -0,0 +1,22 @@ + 'Guest', + 'code' => 'guest', + 'description' => 'Default group for guest users.' + ]); + + UserGroup::create([ + 'name' => 'Registered', + 'code' => 'registered', + 'description' => 'Default group for registered users.' + ]); + } +} diff --git a/plugins/rainlab/user/updates/update_timestamp_nullable.php b/plugins/rainlab/user/updates/update_timestamp_nullable.php new file mode 100644 index 0000000..d0ea82f --- /dev/null +++ b/plugins/rainlab/user/updates/update_timestamp_nullable.php @@ -0,0 +1,21 @@ +timestamp('deleted_at')->nullable(); + }); + } + + public function down() + { + if (Schema::hasColumn('users', 'deleted_at')) { + Schema::table('users', function($table) + { + $table->dropColumn('deleted_at'); + }); + } + } +} diff --git a/plugins/rainlab/user/updates/users_add_guest_flag.php b/plugins/rainlab/user/updates/users_add_guest_flag.php new file mode 100644 index 0000000..e54018c --- /dev/null +++ b/plugins/rainlab/user/updates/users_add_guest_flag.php @@ -0,0 +1,25 @@ +boolean('is_guest')->default(false); + }); + } + + public function down() + { + if (Schema::hasColumn('users', 'is_guest')) { + Schema::table('users', function($table) + { + $table->dropColumn('is_guest'); + }); + } + } +} diff --git a/plugins/rainlab/user/updates/users_add_ip_address.php b/plugins/rainlab/user/updates/users_add_ip_address.php new file mode 100644 index 0000000..8948539 --- /dev/null +++ b/plugins/rainlab/user/updates/users_add_ip_address.php @@ -0,0 +1,31 @@ +string('created_ip_address')->nullable(); + $table->string('last_ip_address')->nullable(); + }); + } + + public function down() + { + if (Schema::hasColumn('users', 'created_ip_address')) { + Schema::table('users', function($table) { + $table->dropColumn('created_ip_address'); + }); + } + + if (Schema::hasColumn('users', 'last_ip_address')) { + Schema::table('users', function($table) { + $table->dropColumn('last_ip_address'); + }); + } + } +} diff --git a/plugins/rainlab/user/updates/users_add_last_seen.php b/plugins/rainlab/user/updates/users_add_last_seen.php new file mode 100644 index 0000000..ea985d8 --- /dev/null +++ b/plugins/rainlab/user/updates/users_add_last_seen.php @@ -0,0 +1,26 @@ +timestamp('last_seen')->nullable(); + }); + } + + public function down() + { + if (Schema::hasColumn('users', 'last_seen')) { + Schema::table('users', function($table) + { + $table->dropColumn('last_seen'); + }); + } + } +} diff --git a/plugins/rainlab/user/updates/users_add_login_column.php b/plugins/rainlab/user/updates/users_add_login_column.php new file mode 100644 index 0000000..1917462 --- /dev/null +++ b/plugins/rainlab/user/updates/users_add_login_column.php @@ -0,0 +1,40 @@ +string('login')->nullable()->index(); + }); + + /* + * Set login for existing users + */ + $users = User::withTrashed()->get(); + foreach ($users as $user) { + $user->login = $user->email; + $user->save(); + } + + Schema::table('users', function($table) + { + $table->unique('login'); + }); + } + + public function down() + { + if (Schema::hasColumn('users', 'login')) { + Schema::table('users', function($table) + { + $table->dropColumn('login'); + }); + } + } +} diff --git a/plugins/rainlab/user/updates/users_add_superuser_flag.php b/plugins/rainlab/user/updates/users_add_superuser_flag.php new file mode 100644 index 0000000..bbab302 --- /dev/null +++ b/plugins/rainlab/user/updates/users_add_superuser_flag.php @@ -0,0 +1,25 @@ +boolean('is_superuser')->default(false); + }); + } + + public function down() + { + if (Schema::hasColumn('users', 'is_superuser')) { + Schema::table('users', function($table) + { + $table->dropColumn('is_superuser'); + }); + } + } +} diff --git a/plugins/rainlab/user/updates/users_add_surname.php b/plugins/rainlab/user/updates/users_add_surname.php new file mode 100644 index 0000000..a3b2849 --- /dev/null +++ b/plugins/rainlab/user/updates/users_add_surname.php @@ -0,0 +1,25 @@ +string('surname')->nullable(); + }); + } + + public function down() + { + if (Schema::hasColumn('users', 'surname')) { + Schema::table('users', function($table) + { + $table->dropColumn('surname'); + }); + } + } +} diff --git a/plugins/rainlab/user/updates/users_rename_login_to_username.php b/plugins/rainlab/user/updates/users_rename_login_to_username.php new file mode 100644 index 0000000..8712111 --- /dev/null +++ b/plugins/rainlab/user/updates/users_rename_login_to_username.php @@ -0,0 +1,26 @@ +renameColumn('login', 'username'); + }); + } + + public function down() + { + if (Schema::hasColumn('users', 'login')) { + Schema::table('users', function($table) + { + $table->renameColumn('username', 'login'); + }); + } + } +} diff --git a/plugins/rainlab/user/updates/version.yaml b/plugins/rainlab/user/updates/version.yaml new file mode 100644 index 0000000..984b1b3 --- /dev/null +++ b/plugins/rainlab/user/updates/version.yaml @@ -0,0 +1,79 @@ +1.0.1: + - Initialize plugin. + - create_users_table.php + - create_throttle_table.php +1.0.2: Seed tables. +1.0.3: Translated hard-coded text to language strings. +1.0.4: Improvements to user-interface for Location manager. +1.0.5: Added contact details for users. +1.0.6: + - Added Mail Blocker utility so users can block specific mail templates. + - create_mail_blockers_table.php +1.0.7: Add back-end Settings page. +1.0.8: Updated the Settings page. +1.0.9: Adds new welcome mail message for users and administrators. +1.0.10: Adds administrator-only activation mode. +1.0.11: + - Users now have an optional login field that defaults to the email field. + - users_add_login_column.php +1.0.12: + - Create a dedicated setting for choosing the login mode. + - users_rename_login_to_username.php +1.0.13: Minor fix to the Account sign in logic. +1.0.14: Minor improvements to the code. +1.0.15: + - Adds last name column to users table (surname). + - users_add_surname.php +1.0.16: Require permissions for settings page too. +1.1.0: Profile fields and Locations have been removed. +1.1.1: + - Users can now be added to groups. + - create_user_groups_table.php + - seed_user_groups_table.php +1.1.2: A raw URL can now be passed as the redirect property in the Account component. +1.1.3: Adds a super user flag to the users table, reserved for future use. +1.1.4: User list can be filtered by the group they belong to. +1.1.5: Adds a new permission to hide the User settings menu item. +1.2.0: + - Users can now deactivate their own accounts. + - users_add_deleted_at.php +1.2.1: New feature for checking if a user is recently active/online. +1.2.2: Add bulk action button to user list. +1.2.3: Included some descriptive paragraphs in the Reset Password component markup. +1.2.4: Added a checkbox for blocking all mail sent to the user. +1.2.5: + - Database maintenance. Updated all timestamp columns to be nullable. + - update_timestamp_nullable.php +1.2.6: + - Add a dedicated last seen column for users. + - users_add_last_seen.php +1.2.7: Minor fix to user timestamp attributes. +1.2.8: Add date range filter to users list. Introduced a logout event. +1.2.9: Add invitation mail for new accounts created in the back-end. +1.3.0: + - Introduced guest user accounts. + - users_add_guest_flag.php + - users_add_superuser_flag.php +1.3.1: User notification variables can now be extended. +1.3.2: Minor fix to the Auth::register method. +1.3.3: Allow prevention of concurrent user sessions via the user settings. +1.3.4: Added force secure protocol property to the account component. +1.4.0: The Notifications tab in User settings has been removed. +1.4.1: Added support for user impersonation. +1.4.2: Fixes security bug in Password Reset component. +1.4.3: Fixes session handling for AJAX requests. +1.4.4: Fixes bug where impersonation touches the last seen timestamp. +1.4.5: Added token fallback process to Account / Reset Password components when parameter is missing. +1.4.6: Fixes Auth::register method signature mismatch with core October CMS Auth library +1.4.7: Fixes redirect bug in Account component / Update translations and separate user and group management. +1.4.8: Fixes a bug where calling MailBlocker::removeBlock could remove all mail blocks for the user. +1.5.0: Required password length is now a minimum of 8 characters. Previous passwords will not be affected until the next password change. +1.5.1: + - User IP addresses are now logged. Introduce registration throttle. + - users_add_ip_address.php +1.5.2: Whitespace from usernames is now trimmed, allowed for username to be added to Reset Password mail templates. +1.5.3: Fixes a bug in the user update functionality if password is not changed. Added highlighting for banned users in user list. +1.5.4: Multiple translation improvements. Added view events to extend user preview and user listing toolbars. +1.5.5: Updated settings icon and description. +1.6.0: Apply persistence settings on activation and registration. Fixes last seen touched when impersonating. Fixes user suspension not clearing. +1.6.1: Adds component property for resetPage in ResetPassword component. diff --git a/plugins/rainlab/user/views/mail/activate.htm b/plugins/rainlab/user/views/mail/activate.htm new file mode 100644 index 0000000..508cf4a --- /dev/null +++ b/plugins/rainlab/user/views/mail/activate.htm @@ -0,0 +1,12 @@ +subject = "Confirm your account" +description = "Activate a new user" +== +Hello {{ name }} + +We need to verify that this is your email address. + +Please click the link below to confirm your account: + +{% partial 'button' url=link type='positive' body %} +Confirm account +{% endpartial %} diff --git a/plugins/rainlab/user/views/mail/invite.htm b/plugins/rainlab/user/views/mail/invite.htm new file mode 100644 index 0000000..187d364 --- /dev/null +++ b/plugins/rainlab/user/views/mail/invite.htm @@ -0,0 +1,13 @@ +subject = "An account has been created for you" +description = "Invite a new user to the website" +== +Hello {{ name }} + +A user account has been created for you. Please use the following login and password to sign in: + +{% partial 'panel' body %} +- Login: `{{ login }}` +- Password: `{{ password|raw }}` +{% endpartial %} + +After signing in you should change your password as soon as possible. diff --git a/plugins/rainlab/user/views/mail/new_user.htm b/plugins/rainlab/user/views/mail/new_user.htm new file mode 100644 index 0000000..d17619b --- /dev/null +++ b/plugins/rainlab/user/views/mail/new_user.htm @@ -0,0 +1,11 @@ +subject = "A new user has signed up" +description = "Notify admins of a new sign up" +layout = "system" +== +Hello {{ name }} + +A new user has just signed up. Here are there details: + +- ID: `{{ id }}` +- Name: `{{ name }}` +- Email: `{{ email }}` diff --git a/plugins/rainlab/user/views/mail/reactivate.htm b/plugins/rainlab/user/views/mail/reactivate.htm new file mode 100644 index 0000000..a311a5a --- /dev/null +++ b/plugins/rainlab/user/views/mail/reactivate.htm @@ -0,0 +1,8 @@ +subject = "Welcome back! Your account has been reactivated" +description = "User has reactivated their account" +== +Welcome back {{ name }} + +This is a message to inform you that you have successfully signed in and reactivated your account. + +If you did not prompt this, we suggest changing your password before deactivating your account again. diff --git a/plugins/rainlab/user/views/mail/restore.htm b/plugins/rainlab/user/views/mail/restore.htm new file mode 100644 index 0000000..48f9437 --- /dev/null +++ b/plugins/rainlab/user/views/mail/restore.htm @@ -0,0 +1,22 @@ +subject = "Requested Password Reset" +description = "User requests a password reset" +== +Hello {{ name }} + +Somebody has requested a password reset for your account, if this was not you, please ignore this email. + +Use this activation code to restore your password: + +{% partial 'promotion' body %} +{{ code }} +{% endpartial %} + +You can use the following link: + +{% partial 'button' url=link type='positive' body %} +Restore password +{% endpartial %} + +{% partial 'subcopy' body %} + **This is an automatic message. Please do not reply to it.** +{% endpartial %} diff --git a/plugins/rainlab/user/views/mail/welcome.htm b/plugins/rainlab/user/views/mail/welcome.htm new file mode 100644 index 0000000..5f5c32d --- /dev/null +++ b/plugins/rainlab/user/views/mail/welcome.htm @@ -0,0 +1,6 @@ +subject = "Your account has been confirmed!" +description = "User confirmed their account" +== +Hello {{ name }} + +This is a message to inform you that your account has been activated successfully. diff --git a/plugins/vdomah/jwtauth/LICENSE b/plugins/vdomah/jwtauth/LICENSE new file mode 100644 index 0000000..0e3364b --- /dev/null +++ b/plugins/vdomah/jwtauth/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 vdomah + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/vdomah/jwtauth/Plugin.php b/plugins/vdomah/jwtauth/Plugin.php new file mode 100644 index 0000000..f14e173 --- /dev/null +++ b/plugins/vdomah/jwtauth/Plugin.php @@ -0,0 +1,66 @@ + [ + 'label' => 'vdomah.jwtauth::lang.settings.page_name', + 'description' => 'vdomah.jwtauth::lang.settings.page_desc', + 'category' => 'vdomah.jwtauth::lang.plugin.name', + 'icon' => 'oc-icon-key', + 'class' => Settings::class, + 'order' => 500, + 'keywords' => 'jwt jwtauth', + 'permissions' => ['vdomah.jwtauth.settings'] + ] + ]; + } + + public function boot() + { + if (empty(Config::get('auth'))) { + Config::set('auth', Config::get('vdomah.jwtauth::auth')); + } + + $this->app->bind(\Illuminate\Auth\AuthManager::class, function($app){ + return new \Illuminate\Auth\AuthManager($app); + }); + + App::register('\Vdomah\JWTAuth\Classes\JWTAuthServiceProvider'); + + $facade = AliasLoader::getInstance(); + $facade->alias('JWTAuth', '\Tymon\JWTAuth\Facades\JWTAuth'); + $facade->alias('JWTFactory', '\Tymon\JWTAuth\Facades\JWTFactory'); + + App::singleton('auth', function ($app) { + return new \Illuminate\Auth\AuthManager($app); + }); + + $this->app['router']->middleware('jwt.auth', '\Tymon\JWTAuth\Middleware\GetUserFromToken'); + $this->app['router']->middleware('jwt.refresh', '\Tymon\JWTAuth\Middleware\RefreshToken'); + + User::extend(function($model) { + $model->addDynamicMethod('getAuthApiAttributes', function () { + return []; + }); + }); + } +} diff --git a/plugins/vdomah/jwtauth/README.md b/plugins/vdomah/jwtauth/README.md new file mode 100644 index 0000000..3076e28 --- /dev/null +++ b/plugins/vdomah/jwtauth/README.md @@ -0,0 +1,110 @@ +# JWT Auth API + +JSON Web Token Authentication for your OctoberCMS API integrated with RainLab.User + +This plugin provides token based authentication to your application. Is based on the awesome package [JSON Web Token Authentication for Laravel & Lumen](https://github.com/tymondesigns/jwt-auth) by Sean Tymon. + +### Requirements + +RainLab.User plugin + +### Installation + +1. [NOT REQUIRED ANY MORE] After plugin installation you need to copy /plugins/vdomah/jwtauth/config/auth.php to {root}/config/auth.php. +If you want to change parameters values of auth.php you can use environment variables in .env (see "Environment options" section). +{root}/config/auth.php is still supported and got priority highest then /plugins/vdomah/jwtauth/config/auth.php. + +2. Generate JWT Authentication Secret. It will be used to sign your tokens. You got 2 options: + - generate using command line: + ````$xslt + php artisan jwt:generate + ```` + You need to assign the generated value to JWT_SECRET in your .env. + - go to Backend > Settings > JWTauth settings and click Generate Secret Key and save. + This value has the highest priority and will override JWT_SECRET value from .env. + +## Endpoints + +The plugin provides 4 endpoints: + +- /api/login + + Makes attempt to authenticate and returns token if succeeded. Also the basic user info is included in the response. + By defult expects 2 parameters to receive: email and password. + +- /api/signup + + Tries to create a user and returns token if succeeded. The user info is included in the response. + By default expects 3 parameters to receive: email, password and password_confirmation. + +- /api/refresh + + Tries to refresh the token and return the new token. + By default expects 1 parameter: token. + +- /api/invalidate + + Tries to invalidate the given token - this can be used as an extra precaution to log the user out. + By default expects 1 parameter: token. + +## Environment options +You're free to define any of this option in your project root .env. +### JWT config +| Variable | Default | +| ------------- |:-------------:| +| JWT_SECRET | | +| JWT_TTL | 60 | +| JWT_REFRESH_TTL | 20160 | +| JWT_ALGO | HS256 | +| JWT_USER_CLASS | RainLab\User\Models\User | +| JWT_IDENTIFIER | id | +| JWT_BLACKLIST_ENABLED | true | +| JWT_PROVIDERS_USER | Tymon\JWTAuth\Providers\User\EloquentUserAdapter | +| JWT_PROVIDERS_JWT | Tymon\JWTAuth\Providers\JWT\NamshiAdapter | +| JWT_PROVIDERS_AUTH | Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter | +| JWT_PROVIDERS_STORAGE | Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter | + +### Laravel auth config +| Variable | Default | +| ------------- |:-------------:| +| AUTH_DEFAULT_GUARD | web | +| AUTH_DEFAULT_PASSWORDS | users | +| AUTH_GUARDS_WEB_DRIVER | session | +| AUTH_GUARDS_WEB_PROVIDER | users | +| AUTH_GUARDS_API_DRIVER | token | +| AUTH_GUARDS_API_PROVIDER | users | +| AUTH_PROVIDERS_USERS_DRIVER | eloquent | +| AUTH_PROVIDERS_USERS_MODEL | \RainLab\User\Models\User | +| AUTH_PASSWORDS_USERS_PROVIDER | users | +| AUTH_PASSWORDS_USERS_EMAIL | auth.emails.password | +| AUTH_PASSWORDS_USERS_TABLE | password_resets | +| AUTH_PASSWORDS_USERS_EXPIRE | 60 | + +## Extending + +### How to use this in another plugin? + +Simply add `->middleware('\Tymon\JWTAuth\Middleware\GetUserFromToken')` to the end of the route in the plugin's routes.php + +eg: +``` +Route::post('test', function (\Request $request) { + return response()->json(('The test was successful')); +})->middleware('\Tymon\JWTAuth\Middleware\GetUserFromToken'); +``` + +Then when making the request set the header "Authorization" to "Bearer `{yourToken}`" + +### How to define own set of user attributes in response? + +For sign up and sign in add corresponding methods getAuthApiSignupAttributes or/and getAuthApiSigninAttributes to User model by extending it in your plugin's boot method: + +``` + User::extend(function($model) { + $model->addDynamicMethod('getAuthApiSignupAttributes', function () use ($model) { + return [ + 'my-attr' => $model->my_attr, + ]; + }); + }); +``` \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/classes/JWTAuthServiceProvider.php b/plugins/vdomah/jwtauth/classes/JWTAuthServiceProvider.php new file mode 100644 index 0000000..3913d4c --- /dev/null +++ b/plugins/vdomah/jwtauth/classes/JWTAuthServiceProvider.php @@ -0,0 +1,24 @@ + [ + 'guard' => env('AUTH_DEFAULT_GUARD', 'web'), + 'passwords' => env('AUTH_DEFAULT_PASSWORDS', 'users'), + ], + /* + |-------------------------------------------------------------------------- + | Authentication Guards + |-------------------------------------------------------------------------- + | + | Next, you may define every authentication guard for your application. + | Of course, a great default configuration has been defined for you + | here which uses session storage and the Eloquent user provider. + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | Supported: "session", "token" + | + */ + 'guards' => [ + 'web' => [ + 'driver' => env('AUTH_GUARDS_WEB_DRIVER', 'session'), + 'provider' => env('AUTH_GUARDS_WEB_PROVIDER', 'users'), + ], + 'api' => [ + 'driver' => env('AUTH_GUARDS_API_DRIVER', 'token'), + 'provider' => env('AUTH_GUARDS_API_PROVIDER', 'users'), + ], + ], + /* + |-------------------------------------------------------------------------- + | User Providers + |-------------------------------------------------------------------------- + | + | All authentication drivers have a user provider. This defines how the + | users are actually retrieved out of your database or other storage + | mechanisms used by this application to persist your user's data. + | + | If you have multiple user tables or models you may configure multiple + | sources which represent each model / table. These sources may then + | be assigned to any extra authentication guards you have defined. + | + | Supported: "database", "eloquent" + | + */ + 'providers' => [ + 'users' => [ + 'driver' => env('AUTH_PROVIDERS_USERS_DRIVER', 'eloquent'), + 'model' => env('AUTH_PROVIDERS_USERS_MODEL', '\RainLab\User\Models\User'), + ], + ], + /* + |-------------------------------------------------------------------------- + | Resetting Passwords + |-------------------------------------------------------------------------- + | + | Here you may set the options for resetting passwords including the view + | that is your password reset e-mail. You may also set the name of the + | table that maintains all of the reset tokens for your application. + | + | You may specify multiple password reset configurations if you have more + | than one user table or model in the application and you want to have + | separate password reset settings based on the specific user types. + | + | The expire time is the number of minutes that the reset token should be + | considered valid. This security feature keeps tokens short-lived so + | they have less time to be guessed. You may change this as needed. + | + */ + 'passwords' => [ + 'users' => [ + 'provider' => env('AUTH_PASSWORDS_USERS_PROVIDER', 'users'), + 'email' => env('AUTH_PASSWORDS_USERS_EMAIL', 'auth.emails.password'), + 'table' => env('AUTH_PASSWORDS_USERS_TABLE', 'password_resets'), + 'expire' => env('AUTH_PASSWORDS_USERS_EXPIRE', 60), + ], + ], +]; \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/config/config.php b/plugins/vdomah/jwtauth/config/config.php new file mode 100644 index 0000000..1b61247 --- /dev/null +++ b/plugins/vdomah/jwtauth/config/config.php @@ -0,0 +1,173 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return [ + + /* + |-------------------------------------------------------------------------- + | JWT Authentication Secret + |-------------------------------------------------------------------------- + | + | Don't forget to set this, as it will be used to sign your tokens. + | A helper command is provided for this: `php artisan jwt:generate` + | + */ + + 'secret' => env('JWT_SECRET'), + + /* + |-------------------------------------------------------------------------- + | JWT time to live + |-------------------------------------------------------------------------- + | + | Specify the length of time (in minutes) that the token will be valid for. + | Defaults to 1 hour + | + */ + + 'ttl' => env('JWT_TTL', 60), + + /* + |-------------------------------------------------------------------------- + | Refresh time to live + |-------------------------------------------------------------------------- + | + | Specify the length of time (in minutes) that the token can be refreshed + | within. I.E. The user can refresh their token within a 2 week window of + | the original token being created until they must re-authenticate. + | Defaults to 2 weeks + | + */ + + 'refresh_ttl' => env('JWT_REFRESH_TTL', 20160), + + /* + |-------------------------------------------------------------------------- + | JWT hashing algorithm + |-------------------------------------------------------------------------- + | + | Specify the hashing algorithm that will be used to sign the token. + | + | See here: https://github.com/namshi/jose/tree/2.2.0/src/Namshi/JOSE/Signer + | for possible values + | + */ + + 'algo' => env('JWT_ALGO', 'HS256'), + + /* + |-------------------------------------------------------------------------- + | User Model namespace + |-------------------------------------------------------------------------- + | + | Specify the full namespace to your User model. + | e.g. 'Acme\Entities\User' + | + */ + + 'user' => env('JWT_USER_CLASS', 'RainLab\User\Models\User'), + + /* + |-------------------------------------------------------------------------- + | User identifier + |-------------------------------------------------------------------------- + | + | Specify a unique property of the user that will be added as the 'sub' + | claim of the token payload. + | + */ + + 'identifier' => env('JWT_IDENTIFIER', 'id'), + + /* + |-------------------------------------------------------------------------- + | Required Claims + |-------------------------------------------------------------------------- + | + | Specify the required claims that must exist in any token. + | A TokenInvalidException will be thrown if any of these claims are not + | present in the payload. + | + */ + + 'required_claims' => ['iss', 'iat', 'exp', 'nbf', 'sub', 'jti'], + + /* + |-------------------------------------------------------------------------- + | Blacklist Enabled + |-------------------------------------------------------------------------- + | + | In order to invalidate tokens, you must have the the blacklist enabled. + | If you do not want or need this functionality, then set this to false. + | + */ + + 'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true), + + /* + |-------------------------------------------------------------------------- + | Providers + |-------------------------------------------------------------------------- + | + | Specify the various providers used throughout the package. + | + */ + + 'providers' => [ + + /* + |-------------------------------------------------------------------------- + | User Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to find the user based + | on the subject claim + | + */ + + 'user' => env('JWT_PROVIDERS_USER', 'Tymon\JWTAuth\Providers\User\EloquentUserAdapter'), + + /* + |-------------------------------------------------------------------------- + | JWT Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to create and decode the tokens. + | + */ + + 'jwt' => env('JWT_PROVIDERS_JWT', 'Tymon\JWTAuth\Providers\JWT\NamshiAdapter'), + + /* + |-------------------------------------------------------------------------- + | Authentication Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to authenticate users. + | + */ + + 'auth' => env('JWT_PROVIDERS_AUTH', 'Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter'), + + /* + |-------------------------------------------------------------------------- + | Storage Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to store tokens in the blacklist + | + */ + + 'storage' => env('JWT_PROVIDERS_STORAGE', 'Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter'), + + ], + +]; diff --git a/plugins/vdomah/jwtauth/lang/en/lang.php b/plugins/vdomah/jwtauth/lang/en/lang.php new file mode 100644 index 0000000..efe631e --- /dev/null +++ b/plugins/vdomah/jwtauth/lang/en/lang.php @@ -0,0 +1,24 @@ + [ + 'name' => 'JWTAuth', + 'description' => 'Provides token based authentication' + ], + 'fields' => [ + 'secret' => 'Secret Key', + 'secret_comment' => 'Overrides JWT_SECRET from .env', + 'btn_generate' => 'Generate Secret Key', + 'signup_fields' => 'Signup Fields', + 'signup_fields_comment' => 'Defaults are email, password, password_confirmation', + 'login_fields' => 'Login Fields', + 'login_fields_comment' => 'Defaults are email, password', + 'section_routes_disable' => 'Disable routes', + 'is_login_disabled' => 'Login route disabled', + 'is_signup_disabled' => 'Signup route disabled', + 'is_refresh_disabled' => 'Refresh route disabled', + 'is_invalidate_disabled' => 'Invalidate route disabled', + ], + 'settings' => [ + 'page_name' => 'JWTauth settings', + 'page_desc' => 'Configure jwt-auth', + ], +]; \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/models/Settings.php b/plugins/vdomah/jwtauth/models/Settings.php new file mode 100644 index 0000000..42b02fb --- /dev/null +++ b/plugins/vdomah/jwtauth/models/Settings.php @@ -0,0 +1,12 @@ + 'api'], function() { + + Route::post('login', function (Request $request) { + if (Settings::get('is_login_disabled')) + App::abort(404, 'Page not found'); + + $login_fields = Settings::get('login_fields', ['email', 'password']); + + $credentials = Input::only($login_fields); + + try { + // verify the credentials and create a token for the user + if (! $token = JWTAuth::attempt($credentials)) { + return response()->json(['error' => 'invalid_credentials'], 401); + } + } catch (JWTException $e) { + // something went wrong + return response()->json(['error' => 'could_not_create_token'], 500); + } + + $userModel = JWTAuth::authenticate($token); + + if ($userModel->methodExists('getAuthApiSigninAttributes')) { + $user = $userModel->getAuthApiSigninAttributes(); + } else { + $user = [ + 'id' => $userModel->id, + 'name' => $userModel->name, + 'surname' => $userModel->surname, + 'username' => $userModel->username, + 'email' => $userModel->email, + // + 'middle_name' => $userModel->middle_name, + 'date_birth' => $userModel->date_birth, + 'passport' => $userModel->passport, + 'place_passport' => $userModel->place_passport, + 'address_residence' => $userModel->address_residence, + 'mobile_phone' => $userModel->mobile_phone, + 'home_phone' => $userModel->home_phone, + // + 'is_activated' => $userModel->is_activated, + ]; + } + // if no errors are encountered we can return a JWT + return response()->json(compact('token', 'user')); + }); + + Route::post('refresh', function (Request $request) { + if (Settings::get('is_refresh_disabled')) + App::abort(404, 'Page not found'); + + $token = Request::get('token'); + + try { + // attempt to refresh the JWT + if (!$token = JWTAuth::refresh($token)) { + return response()->json(['error' => 'could_not_refresh_token'], 401); + } + } catch (Exception $e) { + // something went wrong + return response()->json(['error' => 'could_not_refresh_token'], 500); + } + + // if no errors are encountered we can return a new JWT + return response()->json(compact('token')); + }); + + Route::post('invalidate', function (Request $request) { + if (Settings::get('is_invalidate_disabled')) + App::abort(404, 'Page not found'); + + $token = Request::get('token'); + + try { + // invalidate the token + JWTAuth::invalidate($token); + } catch (Exception $e) { + // something went wrong + return response()->json(['error' => 'could_not_invalidate_token'], 500); + } + + // if no errors we can return a message to indicate that the token was invalidated + return response()->json('token_invalidated'); + }); + + Route::post('signup', function (Request $request) { + if (Settings::get('is_signup_disabled')) + App::abort(404, 'Page not found'); + + $login_fields = Settings::get('signup_fields', ['email', 'password', 'password_confirmation','surname','name','middle_name','date_birth','passport','place_passport','address_residence','mobile_phone','home_phone','username']); + + $credentials = Input::only($login_fields); + // dd($credentials); + try { + $userModel = UserModel::create($credentials); + + if ($userModel->methodExists('getAuthApiSignupAttributes')) { + $user = $userModel->getAuthApiSignupAttributes(); + } else { + $user = [ + 'id' => $userModel->id, + 'name' => $userModel->name, + 'surname' => $userModel->surname, + 'username' => $userModel->username, + 'email' => $userModel->email, + // + 'middle_name' => $userModel->middle_name, + 'date_birth' => $userModel->date_birth, + 'passport' => $userModel->passport, + 'place_passport' => $userModel->place_passport, + 'address_residence' => $userModel->address_residence, + 'mobile_phone' => $userModel->mobile_phone, + 'home_phone' => $userModel->home_phone, + // + 'is_activated' => $userModel->is_activated, + ]; + } + } catch (Exception $e) { + return Response::json(['error' => $e->getMessage()], 401); + } + + $token = JWTAuth::fromUser($userModel); + + return Response::json(compact('token', 'user')); + }); + + Route::get('me', function() { + + $me = \JWTAuth::parseToken()->authenticate() + // ->only(['email', 'password', 'password_confirmation']); + ->only(['email','surname','name','middle_name','date_birth','passport','place_passport','address_residence','mobile_phone','home_phone','username']); + + return Response::json(compact('me')); + + })->middleware('\Tymon\JWTAuth\Middleware\GetUserFromToken'); + + Route::post('me', function(Request $request) { + + $me = \JWTAuth::parseToken()->authenticate(); + if(!$me) { + return Response::json(['error' => 'Not found'], 404); + } + + $data = Input::except(['username']); + + // dd($data); + + $rules = [ + 'email' => 'required|between:6,191|email', + 'name' => 'required', + // 'surname' => 'required', + // 'username' => 'required|digits_between:8,20|numeric', + // 'company' => 'max:191', + ]; + + // $validation = \Validator::make($request, $rules); + // if ($validation->fails()) { + // return Response::json(['error' => $validation->errors()], 400); + // } + + /** + * If password in input data, add rules for password + */ + if (array_key_exists('password', $data) && strlen($data['password'])) { + $rules = [ + 'password' => 'required:create|between:8,255|confirmed', + 'password_confirmation' => 'required_with:password|between:8,255' + ]; + + // $validation = \Validator::make($data, $rules,(new UserModel)->messages); + // if ($validation->fails()) { + // return Response::json(['error' => $validation->errors()], 400); + // } + } + + if($me->email != $data['email']) { + // $me->email_verified = false; + $me->save(); + } + + $me->fill($data); + $me->save(); + + /* + * Password has changed, reauthenticate the user - send new token + */ + if (array_key_exists('password', $data) && strlen($data['password'])) { + + $credentials['username'] = $me->username; + $credentials['password'] = $data['password']; + + try { + // verify the credentials and create a token for the user + if (! $token = JWTAuth::attempt($credentials)) { + return response()->json(['error' => 'invalid_credentials'], 401); + } + } catch (JWTException $e) { + // something went wrong + return response()->json(['error' => 'could_not_create_token'], 500); + } + + $userModel = JWTAuth::authenticate($token); + + // if user is not activated, he will not get token + if(!$userModel->is_activated) { + return response()->json(['error' => 'Not activated'], 403); + } + + if ($userModel->methodExists('getAuthApiSigninAttributes')) { + $user = $userModel->getAuthApiSigninAttributes(); + } else { + // $user = [ + // 'id' => $userModel->id, + // 'name' => $userModel->name, + // 'surname' => $userModel->surname, + // 'username' => $userModel->username, + // 'email' => $userModel->email, + // 'is_activated' => $userModel->is_activated, + // 'user_balance' => $userModel->user_balance, + // 'email_verified' => $userModel->email_verified, + // 'phone_verified' => $userModel->phone_verified + // ]; + $user = [ + 'id' => $userModel->id, + 'name' => $userModel->name, + 'surname' => $userModel->surname, + 'username' => $userModel->username, + 'email' => $userModel->email, + // + 'middle_name' => $userModel->middle_name, + 'date_birth' => $userModel->date_birth, + 'passport' => $userModel->passport, + 'place_passport' => $userModel->place_passport, + 'address_residence' => $userModel->address_residence, + 'mobile_phone' => $userModel->mobile_phone, + 'home_phone' => $userModel->home_phone, + // + 'is_activated' => $userModel->is_activated, + ]; + } + // if no errors are encountered we can return a JWT + return response()->json(compact('token', 'user')); + + } + + return Response::json(compact('me')); + + })->middleware('\Tymon\JWTAuth\Middleware\GetUserFromToken'); + +}); \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/updates/version.yaml b/plugins/vdomah/jwtauth/updates/version.yaml new file mode 100644 index 0000000..5d41d5e --- /dev/null +++ b/plugins/vdomah/jwtauth/updates/version.yaml @@ -0,0 +1,26 @@ +1.0.0: + - Initialize plugin. +1.0.1: + - Custom service provider and config file added. +1.0.2: + - Compability with OctoberCMS builds > 419 (Laravel 5.5) +1.0.3: + - README.md updated +1.0.4: + - Ability to define own set of user attributes in response. +1.0.5: + - /refresh and /invalidate endpoints back. +1.0.6: + - Update README about creating route in another plugin. +1.0.7: + - Compability with OctoberCMS builds > 454 (Authenticatable trait removed) +1.0.8: + - JWT Authentication Secret default value removed from config file. README updated about how to generate the secret. +1.0.9: + - !!! Generate JWT Authentication Secret using php artisan jwt:generate and assign generated value to JWT_SECRET in .env +1.0.10: + - Backend settings to set secret key, signup/login configurable request params. +1.0.11: + - !!! auth.php copying to root/config/ is not required any more. .env options support added to override auth.php and config.php +1.0.12: + - Possibility to disable each endpoint in backend settings \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/vendor/autoload.php b/plugins/vdomah/jwtauth/vendor/autoload.php new file mode 100644 index 0000000..fb1eb20 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + private $classMapAuthoritative = false; + private $missingClasses = array(); + private $apcuPrefix; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/plugins/vdomah/jwtauth/vendor/composer/LICENSE b/plugins/vdomah/jwtauth/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/plugins/vdomah/jwtauth/vendor/composer/autoload_classmap.php b/plugins/vdomah/jwtauth/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..7a91153 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/composer/autoload_classmap.php @@ -0,0 +1,9 @@ + $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', + 'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php', +); diff --git a/plugins/vdomah/jwtauth/vendor/composer/autoload_namespaces.php b/plugins/vdomah/jwtauth/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..4ff9542 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/composer/autoload_namespaces.php @@ -0,0 +1,10 @@ + array($vendorDir . '/kylekatarnls/update-helper/src'), +); diff --git a/plugins/vdomah/jwtauth/vendor/composer/autoload_psr4.php b/plugins/vdomah/jwtauth/vendor/composer/autoload_psr4.php new file mode 100644 index 0000000..1613bdd --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/composer/autoload_psr4.php @@ -0,0 +1,17 @@ + array($vendorDir . '/tymon/jwt-auth/src'), + 'Symfony\\Polyfill\\Util\\' => array($vendorDir . '/symfony/polyfill-util'), + 'Symfony\\Polyfill\\Php56\\' => array($vendorDir . '/symfony/polyfill-php56'), + 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), + 'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'), + 'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'), + 'Namshi\\JOSE\\' => array($vendorDir . '/namshi/jose/src/Namshi/JOSE'), + '' => array($vendorDir . '/nesbot/carbon/src'), +); diff --git a/plugins/vdomah/jwtauth/vendor/composer/autoload_real.php b/plugins/vdomah/jwtauth/vendor/composer/autoload_real.php new file mode 100644 index 0000000..6aac5f4 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/composer/autoload_real.php @@ -0,0 +1,70 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInit3e1deaf74fcf6cb315868dd828db949e::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + if ($useStaticLoader) { + $includeFiles = Composer\Autoload\ComposerStaticInit3e1deaf74fcf6cb315868dd828db949e::$files; + } else { + $includeFiles = require __DIR__ . '/autoload_files.php'; + } + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequire3e1deaf74fcf6cb315868dd828db949e($fileIdentifier, $file); + } + + return $loader; + } +} + +function composerRequire3e1deaf74fcf6cb315868dd828db949e($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + require $file; + + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/composer/autoload_static.php b/plugins/vdomah/jwtauth/vendor/composer/autoload_static.php new file mode 100644 index 0000000..4ab613d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/composer/autoload_static.php @@ -0,0 +1,88 @@ + __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', + 'bd9634f2d41831496de0d3dfe4c94881' => __DIR__ . '/..' . '/symfony/polyfill-php56/bootstrap.php', + ); + + public static $prefixLengthsPsr4 = array ( + 'T' => + array ( + 'Tymon\\JWTAuth\\' => 14, + ), + 'S' => + array ( + 'Symfony\\Polyfill\\Util\\' => 22, + 'Symfony\\Polyfill\\Php56\\' => 23, + 'Symfony\\Polyfill\\Mbstring\\' => 26, + 'Symfony\\Contracts\\Translation\\' => 30, + 'Symfony\\Component\\Translation\\' => 30, + ), + 'N' => + array ( + 'Namshi\\JOSE\\' => 12, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Tymon\\JWTAuth\\' => + array ( + 0 => __DIR__ . '/..' . '/tymon/jwt-auth/src', + ), + 'Symfony\\Polyfill\\Util\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-util', + ), + 'Symfony\\Polyfill\\Php56\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php56', + ), + 'Symfony\\Polyfill\\Mbstring\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', + ), + 'Symfony\\Contracts\\Translation\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/translation-contracts', + ), + 'Symfony\\Component\\Translation\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/translation', + ), + 'Namshi\\JOSE\\' => + array ( + 0 => __DIR__ . '/..' . '/namshi/jose/src/Namshi/JOSE', + ), + ); + + public static $fallbackDirsPsr4 = array ( + 0 => __DIR__ . '/..' . '/nesbot/carbon/src', + ); + + public static $prefixesPsr0 = array ( + 'U' => + array ( + 'UpdateHelper\\' => + array ( + 0 => __DIR__ . '/..' . '/kylekatarnls/update-helper/src', + ), + ), + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit3e1deaf74fcf6cb315868dd828db949e::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit3e1deaf74fcf6cb315868dd828db949e::$prefixDirsPsr4; + $loader->fallbackDirsPsr4 = ComposerStaticInit3e1deaf74fcf6cb315868dd828db949e::$fallbackDirsPsr4; + $loader->prefixesPsr0 = ComposerStaticInit3e1deaf74fcf6cb315868dd828db949e::$prefixesPsr0; + + }, null, ClassLoader::class); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/composer/installed.json b/plugins/vdomah/jwtauth/vendor/composer/installed.json new file mode 100644 index 0000000..8f90ec3 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/composer/installed.json @@ -0,0 +1,552 @@ +[ + { + "name": "kylekatarnls/update-helper", + "version": "1.2.1", + "version_normalized": "1.2.1.0", + "source": { + "type": "git", + "url": "https://github.com/kylekatarnls/update-helper.git", + "reference": "429be50660ed8a196e0798e5939760f168ec8ce9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kylekatarnls/update-helper/zipball/429be50660ed8a196e0798e5939760f168ec8ce9", + "reference": "429be50660ed8a196e0798e5939760f168ec8ce9", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1.0 || ^2.0.0", + "php": ">=5.3.0" + }, + "require-dev": { + "codeclimate/php-test-reporter": "dev-master", + "composer/composer": "2.0.x-dev || ^2.0.0-dev", + "phpunit/phpunit": ">=4.8.35 <6.0" + }, + "time": "2020-04-07T20:44:10+00:00", + "type": "composer-plugin", + "extra": { + "class": "UpdateHelper\\ComposerPlugin" + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "UpdateHelper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kyle", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Update helper" + }, + { + "name": "namshi/jose", + "version": "7.2.3", + "version_normalized": "7.2.3.0", + "source": { + "type": "git", + "url": "https://github.com/namshi/jose.git", + "reference": "89a24d7eb3040e285dd5925fcad992378b82bcff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/namshi/jose/zipball/89a24d7eb3040e285dd5925fcad992378b82bcff", + "reference": "89a24d7eb3040e285dd5925fcad992378b82bcff", + "shasum": "" + }, + "require": { + "ext-date": "*", + "ext-hash": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-spl": "*", + "php": ">=5.5", + "symfony/polyfill-php56": "^1.0" + }, + "require-dev": { + "phpseclib/phpseclib": "^2.0", + "phpunit/phpunit": "^4.5|^5.0", + "satooshi/php-coveralls": "^1.0" + }, + "suggest": { + "ext-openssl": "Allows to use OpenSSL as crypto engine.", + "phpseclib/phpseclib": "Allows to use Phpseclib as crypto engine, use version ^2.0." + }, + "time": "2016-12-05T07:27:31+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Namshi\\JOSE\\": "src/Namshi/JOSE/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Nadalin", + "email": "alessandro.nadalin@gmail.com" + }, + { + "name": "Alessandro Cinelli (cirpo)", + "email": "alessandro.cinelli@gmail.com" + } + ], + "description": "JSON Object Signing and Encryption library for PHP.", + "keywords": [ + "JSON Web Signature", + "JSON Web Token", + "JWS", + "json", + "jwt", + "token" + ] + }, + { + "name": "nesbot/carbon", + "version": "1.39.1", + "version_normalized": "1.39.1.0", + "source": { + "type": "git", + "url": "https://github.com/briannesbitt/Carbon.git", + "reference": "4be0c005164249208ce1b5ca633cd57bdd42ff33" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4be0c005164249208ce1b5ca633cd57bdd42ff33", + "reference": "4be0c005164249208ce1b5ca633cd57bdd42ff33", + "shasum": "" + }, + "require": { + "kylekatarnls/update-helper": "^1.1", + "php": ">=5.3.9", + "symfony/translation": "~2.6 || ~3.0 || ~4.0" + }, + "require-dev": { + "composer/composer": "^1.2", + "friendsofphp/php-cs-fixer": "~2", + "phpunit/phpunit": "^4.8.35 || ^5.7" + }, + "time": "2019-10-14T05:51:36+00:00", + "bin": [ + "bin/upgrade-carbon" + ], + "type": "library", + "extra": { + "update-helper": "Carbon\\Upgrade", + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "http://nesbot.com" + } + ], + "description": "A simple API extension for DateTime.", + "homepage": "http://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ] + }, + { + "name": "symfony/polyfill-mbstring", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c", + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "time": "2020-05-12T16:47:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.17-dev" + } + }, + "installation-source": "source", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/polyfill-php56", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php56.git", + "reference": "e3c8c138280cdfe4b81488441555583aa1984e23" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/e3c8c138280cdfe4b81488441555583aa1984e23", + "reference": "e3c8c138280cdfe4b81488441555583aa1984e23", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-util": "~1.0" + }, + "time": "2020-05-12T16:47:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.17-dev" + } + }, + "installation-source": "source", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php56\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/polyfill-util", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-util.git", + "reference": "4afb4110fc037752cf0ce9869f9ab8162c4e20d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/4afb4110fc037752cf0ce9869f9ab8162c4e20d7", + "reference": "4afb4110fc037752cf0ce9869f9ab8162c4e20d7", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2020-05-12T16:14:59+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.17-dev" + } + }, + "installation-source": "source", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Util\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony utilities for portability of PHP codes", + "homepage": "https://symfony.com", + "keywords": [ + "compat", + "compatibility", + "polyfill", + "shim" + ] + }, + { + "name": "symfony/translation", + "version": "4.4.x-dev", + "version_normalized": "4.4.9999999.9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "46df2290b5dc8a53b4ded00f7e4b49e4ccd2a388" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/46df2290b5dc8a53b4ded00f7e4b49e4ccd2a388", + "reference": "46df2290b5dc8a53b4ded00f7e4b49e4ccd2a388", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^1.1.6|^2" + }, + "conflict": { + "symfony/config": "<3.4", + "symfony/dependency-injection": "<3.4", + "symfony/http-kernel": "<4.4", + "symfony/yaml": "<3.4" + }, + "provide": { + "symfony/translation-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/console": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/finder": "~2.8|~3.0|~4.0|^5.0", + "symfony/http-kernel": "^4.4", + "symfony/intl": "^3.4|^4.0|^5.0", + "symfony/service-contracts": "^1.1.2|^2", + "symfony/yaml": "^3.4|^4.0|^5.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "time": "2020-05-04T15:32:48+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + }, + "installation-source": "source", + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/translation-contracts", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "cfa7f3f5bda0cffdb415d41dd86aa980a3837218" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/cfa7f3f5bda0cffdb415d41dd86aa980a3837218", + "reference": "cfa7f3f5bda0cffdb415d41dd86aa980a3837218", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "time": "2020-05-08T21:41:03+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "source", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ] + }, + { + "name": "tymon/jwt-auth", + "version": "0.5.12", + "version_normalized": "0.5.12.0", + "source": { + "type": "git", + "url": "https://github.com/tymondesigns/jwt-auth.git", + "reference": "614ee3410a1cc18ef13c8d5ffd491b5608afabd8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tymondesigns/jwt-auth/zipball/614ee3410a1cc18ef13c8d5ffd491b5608afabd8", + "reference": "614ee3410a1cc18ef13c8d5ffd491b5608afabd8", + "shasum": "" + }, + "require": { + "illuminate/http": "~5.0", + "illuminate/support": "~5.0", + "namshi/jose": "^5.0 || ^7.0", + "nesbot/carbon": "~1.0", + "php": ">=5.4.0" + }, + "require-dev": { + "illuminate/auth": "~5.0", + "illuminate/console": "~5.0", + "illuminate/database": "~5.0", + "mockery/mockery": "0.9.*", + "phpunit/phpunit": "4.*" + }, + "time": "2017-06-07T21:32:02+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.5-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Tymon\\JWTAuth\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Sean Tymon", + "email": "tymon148@gmail.com", + "homepage": "http://tymondesigns.com", + "role": "Developer" + } + ], + "description": "JSON Web Token Authentication for Laravel 4 and 5", + "homepage": "https://github.com/tymondesigns/jwt-auth", + "keywords": [ + "Authentication", + "JSON Web Token", + "auth", + "jwt", + "laravel", + "tymon" + ] + } +] diff --git a/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/LICENSE b/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/LICENSE new file mode 100644 index 0000000..d55dee5 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2017 https://github.com/pug-php +Copyright (c) 2017 https://github.com/kylekatarnls + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/composer.json b/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/composer.json new file mode 100644 index 0000000..ced8527 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/composer.json @@ -0,0 +1,50 @@ +{ + "name": "kylekatarnls/update-helper", + "description": "Update helper", + "type": "composer-plugin", + "license": "MIT", + "minimum-stability": "dev", + "prefer-stable": true, + "authors": [ + { + "name": "Kyle", + "email": "kylekatarnls@gmail.com" + } + ], + "require": { + "php": ">=5.3.0", + "composer-plugin-api": "^1.1.0 || ^2.0.0" + }, + "require-dev": { + "composer/composer": "2.0.x-dev || ^2.0.0-dev", + "phpunit/phpunit": ">=4.8.35 <6.0", + "codeclimate/php-test-reporter": "dev-master" + }, + "autoload": { + "psr-0": { + "UpdateHelper\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "UpdateHelper\\Tests\\": "tests/UpdateHelper/" + } + }, + "scripts": { + "post-install-cmd": [ + "UpdateHelper\\UpdateHelper::check" + ], + "post-update-cmd": [ + "UpdateHelper\\UpdateHelper::check" + ], + "post-package-install": [ + "UpdateHelper\\UpdateHelper::check" + ], + "post-package-update": [ + "UpdateHelper\\UpdateHelper::check" + ] + }, + "extra": { + "class": "UpdateHelper\\ComposerPlugin" + } +} diff --git a/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/src/UpdateHelper/ComposerPlugin.php b/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/src/UpdateHelper/ComposerPlugin.php new file mode 100644 index 0000000..26d394b --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/src/UpdateHelper/ComposerPlugin.php @@ -0,0 +1,47 @@ +io = $io; + } + + public function deactivate(Composer $composer, IOInterface $io) + { + // Not needed + } + + public function uninstall(Composer $composer, IOInterface $io) + { + // Not needed + } + + public static function getSubscribedEvents() + { + return array( + 'post-autoload-dump' => array( + array('onAutoloadDump', 0), + ), + ); + } + + public function onAutoloadDump(Event $event) + { + if (!class_exists('UpdateHelper\\UpdateHelper')) { + return; + } + + UpdateHelper::check($event); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/src/UpdateHelper/NotUpdateInterfaceInstanceException.php b/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/src/UpdateHelper/NotUpdateInterfaceInstanceException.php new file mode 100644 index 0000000..8213b5e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/src/UpdateHelper/NotUpdateInterfaceInstanceException.php @@ -0,0 +1,9 @@ +read(); + } catch (Exception $e) { + $dependencyConfig = null; + } + + if (is_array($dependencyConfig) && isset($dependencyConfig['extra'], $dependencyConfig['extra'][$key])) { + $classes[$file] = $dependencyConfig['extra'][$key]; + } + } + + protected static function getUpdateHelperConfig(Composer $composer, $key = null) + { + $vendorDir = $composer->getConfig()->get('vendor-dir'); + + $npm = array(); + + foreach (scandir($vendorDir) as $namespace) { + if ($namespace === '.' || $namespace === '..' || !is_dir($directory = $vendorDir.DIRECTORY_SEPARATOR.$namespace)) { + continue; + } + + foreach (scandir($directory) as $dependency) { + if ($dependency === '.' || $dependency === '..' || !is_dir($subDirectory = $directory.DIRECTORY_SEPARATOR.$dependency)) { + continue; + } + + static::appendConfig($npm, $subDirectory, $key); + } + } + + static::appendConfig($npm, dirname($vendorDir), $key); + + return $npm; + } + + /** + * @param Event $event + * @param IOInterface $io + * @param Composer $composer + * @param string[] $subClasses + */ + protected static function checkHelper($event, IOInterface $io, $composer, $class) + { + if (!is_string($class) || !class_exists($class)) { + throw new NotUpdateInterfaceInstanceException(); + } + + try { + $helper = new $class(); + } catch (Exception $e) { + throw new InvalidArgumentException($e->getMessage(), 1000, $e); + } catch (Throwable $e) { + throw new InvalidArgumentException($e->getMessage(), 1000, $e); + } + + if (!($helper instanceof UpdateHelperInterface)) { + throw new NotUpdateInterfaceInstanceException(); + } + + $helper->check(new static($event, $io, $composer)); + } + + /** + * @param string $file + * @param Event $event + * @param IOInterface $io + * @param Composer $composer + * @param string[] $subClasses + */ + protected static function checkFileHelpers($file, $event, IOInterface $io, $composer, array $subClasses) + { + foreach ($subClasses as $class) { + try { + static::checkHelper($event, $io, $composer, $class); + } catch (InvalidArgumentException $exception) { + $io->writeError(static::getErrorMessage($exception, $file, $class)); + continue; + } + } + } + + protected static function getErrorMessage(InvalidArgumentException $exception, $file, $class) + { + if ($exception instanceof NotUpdateInterfaceInstanceException) { + return 'UpdateHelper error in '.$file.":\n".JsonFile::encode($class).' is not an instance of UpdateHelperInterface.'; + } + + return 'UpdateHelper error: '.$exception->getPrevious()->getMessage(). + "\nFile: ".$exception->getPrevious()->getFile(). + "\nLine:".$exception->getPrevious()->getLine(). + "\n\n".$exception->getPrevious()->getTraceAsString(); + } + + public static function check(Event $event) + { + if (!($event instanceof ScriptEvent) && !($event instanceof PackageEvent)) { + return; + } + + $io = $event->getIO(); + $composer = $event->getComposer(); + $autoload = $composer->getConfig()->get('vendor-dir').'/autoload.php'; + + if (file_exists($autoload)) { + include_once $autoload; + } + + $classes = static::getUpdateHelperConfig($composer); + + foreach ($classes as $file => $subClasses) { + static::checkFileHelpers($file, $event, $io, $composer, (array) $subClasses); + } + } + + public function __construct(Event $event, IOInterface $io = null, Composer $composer = null) + { + $this->event = $event; + $this->io = $io ?: (method_exists($event, 'getIO') ? $event->getIO() : null); + $this->composer = $composer ?: (method_exists($event, 'getComposer') ? $event->getComposer() : null); + + if ($this->composer && + ($directory = $this->composer->getConfig()->get('archive-dir')) && + file_exists($file = $directory.'/composer.json') + ) { + $this->composerFilePath = $file; + $this->file = new JsonFile($this->composerFilePath); + $this->dependencies = $this->file->read(); + } + } + + /** + * @return JsonFile + */ + public function getFile() + { + return $this->file; + } + + /** + * @return string + */ + public function getComposerFilePath() + { + return $this->composerFilePath; + } + + /** + * @return Composer + */ + public function getComposer() + { + return $this->composer; + } + + /** + * @return Event + */ + public function getEvent() + { + return $this->event; + } + + /** + * @return IOInterface|null + */ + public function getIo() + { + return $this->io; + } + + /** + * @return array + */ + public function getDependencies() + { + return $this->dependencies; + } + + /** + * @return array + */ + public function getDevDependencies() + { + return isset($this->dependencies['require-dev']) ? $this->dependencies['require-dev'] : array(); + } + + /** + * @return array + */ + public function getProdDependencies() + { + return isset($this->dependencies['require']) ? $this->dependencies['require'] : array(); + } + + /** + * @return array + */ + public function getFlattenDependencies() + { + return array_merge($this->getDevDependencies(), $this->getProdDependencies()); + } + + /** + * @param string $dependency + * + * @return bool + */ + public function hasAsDevDependency($dependency) + { + return isset($this->dependencies['require-dev'][$dependency]); + } + + /** + * @param string $dependency + * + * @return bool + */ + public function hasAsProdDependency($dependency) + { + return isset($this->dependencies['require'][$dependency]); + } + + /** + * @param string $dependency + * + * @return bool + */ + public function hasAsDependency($dependency) + { + return $this->hasAsDevDependency($dependency) || $this->hasAsProdDependency($dependency); + } + + /** + * @param string $dependency + * @param string $version + * + * @return bool + */ + public function isDependencyAtLeast($dependency, $version) + { + if ($this->hasAsProdDependency($dependency)) { + return Semver::satisfies($version, $this->dependencies['require'][$dependency]); + } + + if ($this->hasAsDevDependency($dependency)) { + return Semver::satisfies($version, $this->dependencies['require-dev'][$dependency]); + } + + return false; + } + + /** + * @param string $dependency + * @param string $version + * + * @return bool + */ + public function isDependencyLesserThan($dependency, $version) + { + return !$this->isDependencyAtLeast($dependency, $version); + } + + /** + * @param string $dependency + * @param string $version + * @param array $environments + * + * @throws Exception + * + * @return $this + */ + public function setDependencyVersion($dependency, $version, $environments = array('require', 'require-dev')) + { + return $this->setDependencyVersions(array($dependency => $version), $environments); + } + + /** + * @param array $dependencies + * @param array $environments + * + * @throws Exception + * + * @return $this + */ + public function setDependencyVersions($dependencies, $environments = array('require', 'require-dev')) + { + if (!$this->composerFilePath) { + throw new RuntimeException('No composer instance detected.'); + } + + $touched = false; + + foreach ($environments as $environment) { + foreach ($dependencies as $dependency => $version) { + if (isset($this->dependencies[$environment], $this->dependencies[$environment][$dependency])) { + $this->dependencies[$environment][$dependency] = $version; + $touched = true; + } + } + } + + if ($touched) { + if (!$this->composerFilePath) { + throw new RuntimeException('composer.json not found (custom vendor-dir are not yet supported).'); + } + + $file = new JsonFile($this->composerFilePath); + $file->write($this->dependencies); + } + + return $this; + } + + /** + * @return $this + */ + public function update() + { + $output = shell_exec('composer update --no-scripts'); + + if (!empty($output)) { + $this->write($output); + } + + return $this; + } + + /** + * @param string|array $text + */ + public function write($text) + { + if ($this->io) { + $this->io->write($text); + + return; + } + + if (is_array($text)) { + $text = implode("\n", $text); + } + + echo $text; + } + + /** + * @return bool + */ + public function isInteractive() + { + return $this->io && $this->io->isInteractive(); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/src/UpdateHelper/UpdateHelperInterface.php b/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/src/UpdateHelper/UpdateHelperInterface.php new file mode 100644 index 0000000..3809dc0 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/kylekatarnls/update-helper/src/UpdateHelper/UpdateHelperInterface.php @@ -0,0 +1,8 @@ + 'RS256' + )); + $jws->setPayload(array( + 'uid' => $user->getid(), + )); + + $privateKey = openssl_pkey_get_private("file://path/to/private.key", self::SSL_KEY_PASSPHRASE); + $jws->sign($privateKey); + setcookie('identity', $jws->getTokenString()); +} +``` + +Then your JS app can use the available cookie to execute +authenticated calls, without sending passwords or credentials. + +Once a request is submitted, you only have to verify that it +is a valid call: + +``` php +isValid($public_key, 'RS256')) { + $payload = $jws->getPayload(); + + echo sprintf("Hey, my JS app just did an action authenticated as user #%s", $payload['uid']); +} +``` + +> PROTIP: you can omit the second argument of the isValid() method, so jose will try to validate the token with the algorithm specified in the token's header, though this might expose you to some security issues. +> +> For now we recommend to always explicitely set the algorithm you want to use to validate tokens. + +### PHPSECLIB For RSA Verification + +You may find that you need to use this library in an environment where +[PHP's wrappers for OpenSSL](http://php.net/manual/en/ref.openssl.php) +do not work, or OpenSSL simply is not installed. This library uses +OpenSSL to encrypt by default, but you can specify that you want to use [PHPSecLib](http://phpseclib.sourceforge.net/) for a pure PHP +implementation of RSA encryption. + +In these cases, simply add the optional `'SecLib'` parameter when +constructing a JWS: + +```php +$jws = new JWS(array('alg' => 'RS256'), 'SecLib'); +``` + +You can now use the PHPSecLib implementation of RSA signing. If you use +a password protected private key, you can still submit the private key +to use for signing as a string, as long as you pass the password as the +second parameter into the `sign` method: + +```php +$jws->sign(file_get_contents(SSL_KEYS_PATH . "private.key"), 'tests'); +``` + +You may also load a JWS using the PHPSecLib implementation of RSA verification: + +```php +$jws = JWS::load($tokenString, false, $encoder, 'SecLib'); +``` + +## Under the hood + +In order to [validate the JWS](https://github.com/namshi/jose/blob/master/src/Namshi/JOSE/SimpleJWS.php#L43), +the signature is first [verified](https://github.com/namshi/jose/blob/master/src/Namshi/JOSE/JWS.php#L113) +with a public key and then we will check whether the [token is expired](https://github.com/namshi/jose/blob/master/src/Namshi/JOSE/SimpleJWS.php#L55). + +To give a JWS a TTL, just use the standard `exp` value in the payload: + +``` php +$date = new DateTime('tomorrow'); +$this->jws = new SimpleJWS(array('alg' => 'RS256')); +$this->jws->setPayload(array( + 'exp' => $date->format('U'), +)); +``` + +### Unsecure JWSes + +You can allow [unsecure JWSes](https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#page-12) +by setting the `$allowUnsecure` flag while loading JWSes: + +``` php +JWS::load($this->jws->getTokenString(), true); +``` + +This allows tokens signed with the 'none' algorithms to go through, which is something +you probably don't want to do. Proceed with caution :) + +**Unsecure JWSes are disabled by default since version 2.2.2. You should **not** +use previous versions other than 2.2.2 as they have a security +vulnerability. More info [here](http://tech.namshi.com/blog/2015/02/19/update-your-namshi-slash-jose-installations-as-a-security-vulnerability-was-found/).** + +## Using a custom encoder + +If, for some reason, you need to encode the token in a different way, you can +inject any implementation of `Namshi\JOSE\Base64\Encoder` in a `JWS` instance. +Likewise, `JWS::load()` accepts such an implementation as a second argument. + +## Implementation Specifics + +The library provides a base JWT Class that implements what is needed just for JSON Web Tokens. The JWS Class then extends +the JWT class and adds the implementation for signing and verifying using JSON Web Signatures. The SimpleJWS class extends +the base JWS class and adds validation of a TTL and inclusion of automatic claims. + +## Major Versions + +### 2.x.x to 3.x.x + +Introduced the ability to specify an encryption engine. Added support of PHPSecLib to the existing OpenSSL implementation. + +### 3.x.x to 4.x.x - Not Backwards Compatible + +Added the ability to set custom properties in the header. Moved automatic inclusion of certain claims into an SimpleJWS class from the base JWS class. + +### 6.x.x - Not Backwards Compatible + +#### 6.1.x +- Dropped support for PHP 5.4 +- phpseclib 2.0 + +#### 6.0.x +- Dropped support for PHP 5.3 +- Don't escape slashes when generating signin input. + This may render tokens generated with earlier versions of Jose incompatible. + +### 7.x.x + +#### 7.0.x + +Moved phpseclib and the openssl extension as suggested dependencies. + +## Tests + +Tests are written using PHPUnit for this library. After doing composer install you can execute the following command to run tests: + +``` +./vendor/bin/phpunit +``` + +## Credits + +This library has been inspired by the +[initial work done by @ritou](https://github.com/ritou/php-Akita_JOSE). diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/composer.json b/plugins/vdomah/jwtauth/vendor/namshi/jose/composer.json new file mode 100644 index 0000000..b7f45ca --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/composer.json @@ -0,0 +1,44 @@ +{ + "name": "namshi/jose", + "description": "JSON Object Signing and Encryption library for PHP.", + "license": "MIT", + "keywords": ["jws", "jwt", "json", "json web token", "json web signature", "token"], + "authors": [ + { + "name": "Alessandro Nadalin", + "email": "alessandro.nadalin@gmail.com" + }, + { + "name": "Alessandro Cinelli (cirpo)", + "email": "alessandro.cinelli@gmail.com" + } + ], + "autoload": { + "psr-4": { + "Namshi\\JOSE\\": "src/Namshi/JOSE/" + } + }, + "autoload-dev": { + "psr-4": { + "Namshi\\JOSE\\Test\\": "test/Namshi/JOSE/Test/" + } + }, + "require": { + "ext-date": "*", + "ext-hash": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-spl": "*", + "php": ">=5.5", + "symfony/polyfill-php56": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.5|^5.0", + "satooshi/php-coveralls": "^1.0", + "phpseclib/phpseclib": "^2.0" + }, + "suggest": { + "ext-openssl": "Allows to use OpenSSL as crypto engine.", + "phpseclib/phpseclib": "Allows to use Phpseclib as crypto engine, use version ^2.0." + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/phpunit.xml.dist b/plugins/vdomah/jwtauth/vendor/namshi/jose/phpunit.xml.dist new file mode 100644 index 0000000..aa9beb8 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/phpunit.xml.dist @@ -0,0 +1,26 @@ + + + + + ./tests + + + + + ./src + + + diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Base64/Base64Encoder.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Base64/Base64Encoder.php new file mode 100644 index 0000000..459bdfb --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Base64/Base64Encoder.php @@ -0,0 +1,26 @@ +supportedEncryptionEngines)) { + throw new InvalidArgumentException(sprintf('Encryption engine %s is not supported', $encryptionEngine)); + } + + if ('SecLib' === $encryptionEngine && version_compare(PHP_VERSION, '7.0.0-dev') >= 0) { + throw new InvalidArgumentException("phpseclib 1.0.0(LTS), even the latest 2.0.0, doesn't support PHP7 yet"); + } + + $this->encryptionEngine = $encryptionEngine; + + parent::__construct(array(), $header); + } + + /** + * Signs the JWS signininput. + * + * @param resource|string $key + * @param optional string $password + * + * @return string + */ + public function sign($key, $password = null) + { + $this->signature = $this->getSigner()->sign($this->generateSigninInput(), $key, $password); + $this->isSigned = true; + + return $this->signature; + } + + /** + * Returns the signature representation of the JWS. + * + * @return string + */ + public function getSignature() + { + if ($this->isSigned()) { + return $this->signature; + } + + return; + } + + /** + * Checks whether the JSW has already been signed. + * + * @return bool + */ + public function isSigned() + { + return (bool) $this->isSigned; + } + + /** + * Returns the string representing the JWT. + * + * @return string + */ + public function getTokenString() + { + $signinInput = $this->generateSigninInput(); + + return sprintf('%s.%s', $signinInput, $this->encoder->encode($this->getSignature())); + } + + /** + * Creates an instance of a JWS from a JWT. + * + * @param string $jwsTokenString + * @param bool $allowUnsecure + * @param Encoder $encoder + * @param string $encryptionEngine + * + * @return JWS + * + * @throws \InvalidArgumentException + */ + public static function load($jwsTokenString, $allowUnsecure = false, Encoder $encoder = null, $encryptionEngine = 'OpenSSL') + { + if ($encoder === null) { + $encoder = strpbrk($jwsTokenString, '+/=') ? new Base64Encoder() : new Base64UrlSafeEncoder(); + } + + $parts = explode('.', $jwsTokenString); + + if (count($parts) === 3) { + $header = json_decode($encoder->decode($parts[0]), true); + $payload = json_decode($encoder->decode($parts[1]), true); + + if (is_array($header) && is_array($payload)) { + if (strtolower($header['alg']) === 'none' && !$allowUnsecure) { + throw new InvalidArgumentException(sprintf('The token "%s" cannot be validated in a secure context, as it uses the unallowed "none" algorithm', $jwsTokenString)); + } + + $jws = new static($header, $encryptionEngine); + + $jws->setEncoder($encoder) + ->setHeader($header) + ->setPayload($payload) + ->setOriginalToken($jwsTokenString) + ->setEncodedSignature($parts[2]); + + return $jws; + } + } + + throw new InvalidArgumentException(sprintf('The token "%s" is an invalid JWS', $jwsTokenString)); + } + + /** + * Verifies that the internal signin input corresponds to the encoded + * signature previously stored (@see JWS::load). + * + * @param resource|string $key + * @param string $algo The algorithms this JWS should be signed with. Use it if you want to restrict which algorithms you want to allow to be validated. + * + * @return bool + */ + public function verify($key, $algo = null) + { + if (empty($key) || ($algo && $this->header['alg'] !== $algo)) { + return false; + } + + $decodedSignature = $this->encoder->decode($this->getEncodedSignature()); + $signinInput = $this->getSigninInput(); + + return $this->getSigner()->verify($key, $decodedSignature, $signinInput); + } + + /** + * Get the original token signin input if it exists, otherwise generate the + * signin input for the current JWS + * + * @return string + */ + private function getSigninInput() + { + $parts = explode('.', $this->originalToken); + + if (count($parts) >= 2) { + return sprintf('%s.%s', $parts[0], $parts[1]); + } + + return $this->generateSigninInput(); + } + + /** + * Sets the original base64 encoded token. + * + * @param string $originalToken + * + * @return JWS + */ + private function setOriginalToken($originalToken) + { + $this->originalToken = $originalToken; + + return $this; + } + + /** + * Returns the base64 encoded signature. + * + * @return string + */ + public function getEncodedSignature() + { + return $this->encodedSignature; + } + + /** + * Sets the base64 encoded signature. + * + * @param string $encodedSignature + * + * @return JWS + */ + public function setEncodedSignature($encodedSignature) + { + $this->encodedSignature = $encodedSignature; + + return $this; + } + + /** + * Returns the signer responsible to encrypting / decrypting this JWS. + * + * @return SignerInterface + * + * @throws \InvalidArgumentException + */ + protected function getSigner() + { + $signerClass = sprintf('Namshi\\JOSE\\Signer\\%s\\%s', $this->encryptionEngine, $this->header['alg']); + + if (class_exists($signerClass)) { + return new $signerClass(); + } + + throw new InvalidArgumentException( + sprintf("The algorithm '%s' is not supported for %s", $this->header['alg'], $this->encryptionEngine)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/JWT.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/JWT.php new file mode 100644 index 0000000..9c67368 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/JWT.php @@ -0,0 +1,107 @@ +setPayload($payload); + $this->setHeader($header); + $this->setEncoder(new Base64UrlSafeEncoder()); + } + + /** + * @param Encoder $encoder + */ + public function setEncoder(Encoder $encoder) + { + $this->encoder = $encoder; + + return $this; + } + + /** + * Generates the signininput for the current JWT. + * + * @return string + */ + public function generateSigninInput() + { + $base64payload = $this->encoder->encode(json_encode($this->getPayload(), JSON_UNESCAPED_SLASHES)); + $base64header = $this->encoder->encode(json_encode($this->getHeader(), JSON_UNESCAPED_SLASHES)); + + return sprintf('%s.%s', $base64header, $base64payload); + } + + /** + * Returns the payload of the JWT. + * + * @return array + */ + public function getPayload() + { + return $this->payload; + } + + /** + * Sets the payload of the current JWT. + * + * @param array $payload + */ + public function setPayload(array $payload) + { + $this->payload = $payload; + + return $this; + } + + /** + * Returns the header of the JWT. + * + * @return array + */ + public function getHeader() + { + return $this->header; + } + + /** + * Sets the header of this JWT. + * + * @param array $header + */ + public function setHeader(array $header) + { + $this->header = $header; + + return $this; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/ECDSA.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/ECDSA.php new file mode 100644 index 0000000..29f237d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/ECDSA.php @@ -0,0 +1,108 @@ += 0) { + throw new \InvalidArgumentException("phpseclib 1.0.0(LTS), even the latest 2.0.0, doesn't support PHP7 yet"); + } + } + + /** + * {@inheritdoc} + */ + protected function supportsKey($key) + { + if (false === parent::supportsKey($key)) { + return false; + } + + // openssl_sign with EC keys was introduced in this PHP release + $minVersions = array( + '5.4' => '5.4.26', + '5.5' => '5.5.10', + '5.6' => '5.6.0', + ); + + if (isset($minVersions[PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION]) && + version_compare(PHP_VERSION, $minVersions[PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION], '<')) { + return false; + } + + $keyDetails = openssl_pkey_get_details($key); + + if (0 === preg_match('/-----BEGIN PUBLIC KEY-----([^-]+)-----END PUBLIC KEY-----/', $keyDetails['key'], $matches)) { + return false; + } + $publicKey = trim($matches[1]); + $asn1 = new ASN1(); + + /* + * http://tools.ietf.org/html/rfc3279#section-2.2.3 + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * For ECDSA Signature Algorithm: + * algorithm: ansi-X9-62 => 1.2.840.10045.2.1 + * parameters: id-ecSigType => 1.2.840.10045.x.y.z + * + */ + $asnAlgorithmIdentifier = array( + 'type' => ASN1::TYPE_SEQUENCE, + 'children' => array( + 'ansi-X9-62' => array( + 'type' => ASN1::TYPE_OBJECT_IDENTIFIER, + ), + 'id-ecSigType' => array( + 'type' => ASN1::TYPE_OBJECT_IDENTIFIER, + ), + ), + ); + + /* + * http://tools.ietf.org/html/rfc5280#section-4.1 + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + */ + $asnSubjectPublicKeyInfo = array( + 'type' => ASN1::TYPE_SEQUENCE, + 'children' => array( + 'algorithm' => $asnAlgorithmIdentifier, + 'subjectPublicKey' => array( + 'type' => ASN1::TYPE_BIT_STRING, + ), + ), + ); + + $decoded = $asn1->decodeBER(base64_decode($publicKey)); + $mappedDetails = $asn1->asn1map($decoded[0], $asnSubjectPublicKeyInfo); + + return isset($mappedDetails['algorithm']['id-ecSigType']) ? $this->getSupportedECDSACurve() === $mappedDetails['algorithm']['id-ecSigType'] : false; + } + + /** + * {@inheritdoc} + */ + protected function getSupportedPrivateKeyType() + { + return defined('OPENSSL_KEYTYPE_EC') ? OPENSSL_KEYTYPE_EC : false; + } + + /** + * Returns the ECDSA curve supported in this signer. + * + * @return string + */ + abstract protected function getSupportedECDSACurve(); +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/ES256.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/ES256.php new file mode 100644 index 0000000..b1f8aa2 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/ES256.php @@ -0,0 +1,19 @@ +getHashingAlgorithm(), $input, (string) $key, true); + } + + /** + * To prevent timing attacks we are using PHP 5.6 native function hash_equals, + * in case of PHP < 5.6 a timing safe equals comparison function. + * + * more info here: + * http://blog.ircmaxell.com/2014/11/its-all-about-time.html + * + * + * {@inheritdoc} + */ + public function verify($key, $signature, $input) + { + $signedInput = $this->sign($input, $key); + + return $this->timingSafeEquals($signedInput, $signature); + } + + /** + * A timing safe equals comparison. + * + * @param string $signature the internal signature to be checked + * @param string $signedInput The signed input submitted value + * + * @return bool true if the two strings are identical. + */ + public function timingSafeEquals($known, $input) + { + return hash_equals($known, $input); + } + + /** + * Returns the hashing algorithm used in this signer. + * + * @return string + */ + abstract public function getHashingAlgorithm(); +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/HS256.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/HS256.php new file mode 100644 index 0000000..1ec3ac6 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/HS256.php @@ -0,0 +1,14 @@ +getKeyResource($key, $password); + if (!$this->supportsKey($keyResource)) { + throw new InvalidArgumentException('Invalid key supplied.'); + } + + $signature = null; + openssl_sign($input, $signature, $keyResource, $this->getHashingAlgorithm()); + + return $signature; + } + + /** + * {@inheritdoc} + */ + public function verify($key, $signature, $input) + { + $keyResource = $this->getKeyResource($key); + if (!$this->supportsKey($keyResource)) { + throw new InvalidArgumentException('Invalid key supplied.'); + } + + $result = openssl_verify($input, $signature, $keyResource, $this->getHashingAlgorithm()); + + if ($result === -1) { + throw new RuntimeException('Unknown error during verification.'); + } + + return (bool) $result; + } + + /** + * Converts a string representation of a key into an OpenSSL resource. + * + * @param string|resource $key + * @param string $password + * + * @return resource OpenSSL key resource + */ + protected function getKeyResource($key, $password = null) + { + if (is_resource($key)) { + return $key; + } + + $resource = openssl_pkey_get_public($key) ?: openssl_pkey_get_private($key, $password); + if ($resource === false) { + throw new RuntimeException('Could not read key resource: ' . openssl_error_string()); + } + return $resource; + } + + /** + * Check if the key is supported by this signer. + * + * @param resource $key Public or private key + * + * @return bool + */ + protected function supportsKey($key) + { + // OpenSSL 0.9.8+ + $keyDetails = openssl_pkey_get_details($key); + + return isset($keyDetails['type']) ? $this->getSupportedPrivateKeyType() === $keyDetails['type'] : false; + } + + /** + * Returns the hashing algorithm used in this signer. + * + * @return string + */ + abstract protected function getHashingAlgorithm(); + + /** + * Returns the private key type supported in this signer. + * + * @return string + */ + abstract protected function getSupportedPrivateKeyType(); +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/RS256.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/RS256.php new file mode 100644 index 0000000..e90ee92 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/OpenSSL/RS256.php @@ -0,0 +1,14 @@ +encryptionAlgorithm->setPassword($password); + } + + if (!$this->encryptionAlgorithm->loadKey($key)) { + throw new InvalidArgumentException('Invalid key supplied.'); + } + + return $this->encryptionAlgorithm->sign($input); + } + + /** + * {@inheritdoc} + */ + public function verify($key, $signature, $input) + { + if (!$this->encryptionAlgorithm->loadKey($key)) { + throw new InvalidArgumentException('Invalid key supplied.'); + } + + return $this->encryptionAlgorithm->verify($input, $signature); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RS256.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RS256.php new file mode 100644 index 0000000..d8cde51 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RS256.php @@ -0,0 +1,13 @@ +encryptionAlgorithm->setHash('sha256'); + $this->encryptionAlgorithm->setMGFHash('sha256'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RS384.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RS384.php new file mode 100644 index 0000000..ba8b612 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RS384.php @@ -0,0 +1,13 @@ +encryptionAlgorithm->setHash('sha384'); + $this->encryptionAlgorithm->setMGFHash('sha384'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RS512.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RS512.php new file mode 100644 index 0000000..ab8680e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RS512.php @@ -0,0 +1,13 @@ +encryptionAlgorithm->setHash('sha512'); + $this->encryptionAlgorithm->setMGFHash('sha512'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RSA.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RSA.php new file mode 100644 index 0000000..e06588d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SecLib/RSA.php @@ -0,0 +1,13 @@ +encryptionAlgorithm = new CryptRSA(); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SignerInterface.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SignerInterface.php new file mode 100644 index 0000000..94fe87e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/src/Namshi/JOSE/Signer/SignerInterface.php @@ -0,0 +1,28 @@ +verify($key, $algo) && !$this->isExpired(); + } + + /** + * Checks whether the token is expired based on the 'exp' value. + *it. + * + * @return bool + */ + public function isExpired() + { + $payload = $this->getPayload(); + + if (isset($payload['exp'])) { + $now = new \DateTime('now'); + + if (is_int($payload['exp'])) { + return ($now->getTimestamp() - $payload['exp']) > 0; + } + + if (is_numeric($payload['exp'])) { + return ($now->format('U') - $payload['exp']) > 0; + } + } + + return false; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/BCJWSTest.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/BCJWSTest.php new file mode 100644 index 0000000..dab799c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/BCJWSTest.php @@ -0,0 +1,37 @@ + 'ae123123'), + array('username' => 'asdasdasd'), + array('anything' => '!@#$%^&*()_+'), + ); + + foreach ($data as $payload) { + $jwsOld = new JWS(array('alg' => 'RS256')); + $jwsOld->setEncoder(new Base64Encoder()); + $jwsOld->setPayload($payload); + $jwsOld->sign(openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', self::SSL_KEY_PASSPHRASE)); + + $t = $jwsOld->getTokenString(); + + $jwsNew = JWS::load($t); + $this->assertTrue($jwsNew->verify(openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'))); + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/JWSTest.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/JWSTest.php new file mode 100644 index 0000000..f157512 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/JWSTest.php @@ -0,0 +1,294 @@ + 'b', + ); + $this->jws = new JWS(array('alg' => 'RS256')); + $this->jws->setPayload($data); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testLoadingUnsecureJwsWithNoneAlgo() + { + $date = new DateTime('tomorrow'); + $data = array( + 'a' => 'b', + 'exp' => $date->format('U'), + ); + $this->jws = new JWS(array('alg' => 'None')); + $this->jws->setPayload($data); + $this->jws->sign('111'); + + $jws = JWS::load($this->jws->getTokenString()); + $this->assertFalse($jws->verify('111')); + + $payload = $jws->getPayload(); + $this->assertEquals('b', $payload['a']); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testLoadingUnsecureJwsWithLowercaseNone() + { + $date = new DateTime('tomorrow'); + $data = array( + 'a' => 'b', + 'exp' => $date->format('U'), + ); + $this->jws = new JWS(array('alg' => 'none')); + $this->jws->setPayload($data); + $this->jws->sign('111'); + + $jws = JWS::load($this->jws->getTokenString()); + $this->assertFalse($jws->verify('111')); + + $payload = $jws->getPayload(); + $this->assertEquals('b', $payload['a']); + } + + public function testAllowingUnsecureJws() + { + $date = new DateTime('tomorrow'); + $data = array( + 'a' => 'b', + 'exp' => $date->format('U'), + ); + $this->jws = new JWS(array('alg' => 'None')); + $this->jws->setPayload($data); + $this->jws->sign('111'); + + $jws = JWS::load($this->jws->getTokenString(), true); + $this->assertTrue($jws->verify('111')); + + $payload = $jws->getPayload(); + $this->assertEquals('b', $payload['a']); + } + + public function testRestrictingTheAlgorithmsKo() + { + $this->jws = new JWS(array('alg' => 'HS256')); + $this->jws->sign('12345'); + + $jws = JWS::load($this->jws->getTokenString()); + $this->assertFalse($jws->verify('12345', 'RS256')); + } + + public function testRestrictingTheAlgorithmsOk() + { + $date = new DateTime('tomorrow'); + $data = array( + 'a' => 'b', + 'exp' => $date->format('U'), + ); + $this->jws = new JWS(array('alg' => 'HS256')); + $this->jws->setPayload($data); + $this->jws->sign('123'); + + $jws = JWS::load($this->jws->getTokenString()); + $this->assertTrue($jws->verify('123', 'HS256')); + } + + public function testVerificationRS256() + { + $privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', self::SSL_KEY_PASSPHRASE); + $this->jws->sign($privateKey); + + $jws = JWS::load($this->jws->getTokenString()); + $public_key = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->assertTrue($jws->verify($public_key)); + + $payload = $jws->getPayload(); + $this->assertEquals('b', $payload['a']); + } + + public function testVerificationRS256KeyAsString() + { + $privateKey = file_get_contents(TEST_DIR.'/private.key'); + $this->jws->sign($privateKey, self::SSL_KEY_PASSPHRASE); + + $jws = JWS::load($this->jws->getTokenString()); + $public_key = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->assertTrue($jws->verify($public_key)); + + $payload = $jws->getPayload(); + $this->assertEquals('b', $payload['a']); + } + + public function testUseOfCustomEncoder() + { + $encoder = $this->prophesize('Namshi\JOSE\Base64\Encoder'); + $encoder + ->decode(Argument::any()) + ->willReturn('{"whatever": "the payload should be"}') + ->shouldBeCalled(); + $encoder + ->decode(Argument::any()) + ->willReturn('{"alg": "test"}') + ->shouldBeCalled(); + JWS::load($this->jws->getTokenString(), false, $encoder->reveal()); + } + + public function testVerificationThatTheJWSIsSigned() + { + $privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', self::SSL_KEY_PASSPHRASE); + $this->jws->sign($privateKey); + $this->assertTrue($this->jws->isSigned()); + } + + public function testVerificationThatTheJWSIsNotSigned() + { + $this->assertFalse($this->jws->isSigned()); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testWrongVerificationRS256() + { + $privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', self::SSL_KEY_PASSPHRASE); + $this->jws->sign($privateKey); + + $jws = JWS::load('eyJhbGciOiJ0ZXN0In0=.eyJhbGciOiJ0ZXN0In0=.eyJhbGciOiJ0ZXN0In0='); + $public_key = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->assertFalse($jws->verify($public_key)); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testLoadingAMalformedTokenString() + { + JWS::load('test.Test.TEST'); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testLoadingAMalformedTokenString2() + { + JWS::load('test'); + } + + public function testSignAndVerifyWithFalsePublicKey() + { + $public_key = false; + $jwsHMAC = new JWS(array('alg' => 'HS256')); + + $jwsHMAC->sign(false); + $jws = JWS::load($jwsHMAC->getTokenString()); + + $this->assertFalse($jws->verify($public_key)); + } + + public function testSignAndVerifyWithEmptyStringPublicKey() + { + $public_key = false; + $jwsHMAC = new JWS(array('alg' => 'HS256')); + + $jwsHMAC->sign(''); + $jws = JWS::load($jwsHMAC->getTokenString()); + + $this->assertFalse($jws->verify($public_key)); + } + + public function testLoadingWithAnyOrderOfHeaders() + { + $privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', self::SSL_KEY_PASSPHRASE); + $public_key = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + + $this->jws = new JWS(array('alg' => 'RS256', 'custom' => '1')); + + $header = $this->jws->getHeader(); + $reversedHeader = array_reverse($header); + $this->assertFalse($header === $reversedHeader); + + $this->jws->setHeader($reversedHeader); + $this->jws->sign($privateKey); + + $tokenString = $this->jws->getTokenString(); + $jws = JWS::load($tokenString); + $this->assertTrue($reversedHeader === $jws->getHeader()); + } + + public function testSignAndVerifyWithSecLib() + { + if (version_compare(PHP_VERSION, '7.0.0-dev') >= 0) { + $this->setExpectedException('InvalidArgumentException'); + } + + $jwsRSA = new JWS(array('alg' => 'RS256'), 'SecLib'); + $data = array('a' => 'b'); + $jwsRSA->setPayload($data); + + $jwsRSA->sign(file_get_contents(SSL_KEYS_PATH.'private.key'), 'tests'); + $jws = JWS::load($jwsRSA->getTokenString(), false, null, 'SecLib'); + + $this->assertTrue($jws->verify(file_get_contents(SSL_KEYS_PATH.'public.key', 'RS256'))); + } + + public function testConstructionFromHeader() + { + $header = array('alg' => 'RS256', 'test' => true); + $jws = new JWS($header); + + $this->assertTrue($header == $jws->getHeader()); + } + + public function testVerificationCustomizedHeader() + { + $header = $this->jws->getHeader(); + $header['test'] = true; + $this->jws->setHeader($header); + + $privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', self::SSL_KEY_PASSPHRASE); + $this->jws->sign($privateKey); + + $jws = JWS::load($this->jws->getTokenString()); + $public_key = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $headerFromSig = $jws->getHeader(); + + $this->assertSame($headerFromSig['test'], true); + $this->assertTrue($jws->verify($public_key)); + } + + public function testVerificationWithJsonThatContainsWhitespace() + { + $header = '{ + "alg": "HS256" + }'; + + $payload = '{ + "a": "b" + }'; + + $encoder = new Base64UrlSafeEncoder(); + $signer = new HS256(); + + $token = sprintf('%s.%s', $encoder->encode($header), $encoder->encode($payload)); + $signature = $encoder->encode($signer->sign($token, '123')); + $jwsToken = sprintf('%s.%s', $token, $signature); + + $jws = JWS::load($jwsToken); + + $this->assertTrue($jws->verify('123')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/JWTTest.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/JWTTest.php new file mode 100644 index 0000000..e289888 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/JWTTest.php @@ -0,0 +1,45 @@ + 'a', 'iat' => 1421161177); + $header = array('a' => 'b'); + $jwt = new JWT($payload, $header); + $encoder = new Base64UrlSafeEncoder(); + + $this->assertEquals(sprintf('%s.%s', $encoder->encode(json_encode($header)), $encoder->encode(json_encode($payload))), $jwt->generateSigninInput()); + } + + public function testGenerationOfTheSigninInputCanHandleSlashes() + { + $encoder = new Base64UrlSafeEncoder(); + $json_string = '{"a":"/b/"}'; + $encoded_json_string = $encoder->encode($json_string); + $jwt = new JWT(json_decode($json_string, true), json_decode($json_string, true)); + + $this->assertEquals(sprintf('%s.%s', $encoded_json_string, $encoded_json_string), $jwt->generateSigninInput()); + } + + public function testPayload() + { + $jwt = new JWT(array('a' => 'b'), array()); + $payload = $jwt->getPayload(); + + $this->assertSame(array('a' => 'b'), $payload); + + $jwt = new JWT(array('a' => 'b'), array()); + $jwt->setPayload(array('b' => 'a')); + $payload = $jwt->getPayload(); + + $this->assertSame($payload['b'], 'a'); + $this->assertSame(array('b' => 'a'), $payload); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/ES256Test.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/ES256Test.php new file mode 100644 index 0000000..d2d4ea6 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/ES256Test.php @@ -0,0 +1,43 @@ +markTestSkipped(); + } + $this->privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.es256.key'); + $this->public = openssl_pkey_get_public(SSL_KEYS_PATH.'public.es256.key'); + $this->signer = new ES256(); + } + + public function testVerificationWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKey); + $this->assertInternalType('bool', $this->signer->verify($this->public, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->public, $encrypted, 'aaa')); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Invalid key supplied. + */ + public function testWrongKeyCurve() + { + $privateKey512 = openssl_pkey_get_private(SSL_KEYS_PATH.'private.es512.key'); + $this->signer->sign('aaa', $privateKey512); + } + + public function testSigningWorksProperly() + { + $this->assertInternalType('string', $this->signer->sign('aaa', $this->privateKey)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/ES384Test.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/ES384Test.php new file mode 100644 index 0000000..88119bf --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/ES384Test.php @@ -0,0 +1,33 @@ +markTestSkipped(); + } + $this->privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.es384.key', 'tests'); + $this->public = openssl_pkey_get_public(SSL_KEYS_PATH.'public.es384.key'); + $this->signer = new ES384(); + } + + public function testVerificationWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKey); + $this->assertInternalType('bool', $this->signer->verify($this->public, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->public, $encrypted, 'aaa')); + } + + public function testSigningWorksProperly() + { + $this->assertInternalType('string', $this->signer->sign('aaa', $this->privateKey)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/ES512Test.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/ES512Test.php new file mode 100644 index 0000000..570f70e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/ES512Test.php @@ -0,0 +1,33 @@ +markTestSkipped(); + } + $this->privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.es512.key'); + $this->public = openssl_pkey_get_public(SSL_KEYS_PATH.'public.es512.key'); + $this->signer = new ES512(); + } + + public function testVerificationWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKey); + $this->assertInternalType('bool', $this->signer->verify($this->public, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->public, $encrypted, 'aaa')); + } + + public function testSigningWorksProperly() + { + $this->assertInternalType('string', $this->signer->sign('aaa', $this->privateKey)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/HS256Test.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/HS256Test.php new file mode 100644 index 0000000..ac56752 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/HS256Test.php @@ -0,0 +1,19 @@ +sign('aaa', 'foo'); + $this->assertEquals($signature, base64_decode('P2Pb8e2Ja4P4YnTZ3EF002RKpUpOnfjIy0uLNT0R1J0=')); + + $this->assertTrue($signer->verify('foo', $signature, 'aaa')); + $this->assertFalse($signer->verify('bar', $signature, 'aaa')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/HS384Test.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/HS384Test.php new file mode 100644 index 0000000..44d705d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/HS384Test.php @@ -0,0 +1,20 @@ +sign('aaa', 'foo'); + + $this->assertEquals($signature, base64_decode('W6Cd7qZknNYIXOxTrpEWFFwfuX0e2j59hTH4kVFh5o+9rcnfNtphLg4V8YXfkXGF')); + + $this->assertTrue($signer->verify('foo', $signature, 'aaa')); + $this->assertFalse($signer->verify('bar', $signature, 'aaa')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/HS512Test.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/HS512Test.php new file mode 100644 index 0000000..270dd83 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/HS512Test.php @@ -0,0 +1,20 @@ +sign('aaa', 'foo'); + + $this->assertEquals($signature, base64_decode('GysqRX8GoD6BCTrI5sJy1ptn9A7vbDlvFOnaAxO/t+BD8KVrVAUVcHMxgM68ZNxnUNkb7kNSq3YxkCV4pBvTjg==')); + + $this->assertTrue($signer->verify('foo', $signature, 'aaa')); + $this->assertFalse($signer->verify('bar', $signature, 'aaa')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/KeyFormatTest.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/KeyFormatTest.php new file mode 100644 index 0000000..6ee8d9a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/KeyFormatTest.php @@ -0,0 +1,67 @@ +privateKeyResource = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', 'tests'); + $this->privateKeyString = "-----BEGIN PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN91kQxBuaze3WjI\nCNjeR/HD8E3kDzp89+Lhtn3tMish4yQxhNl6BEkabuS3pUj3WDP6+AFjBVqA1j3f\nu8Wqu7hRJDPHOs2kCII+LhIqvqQTLx/nvNOUhW2DimKn0HuHnlwJODq0MHFJEq5R\nrJH+mFGsP9yMGz4MxA04E2RVbUJRAgMBAAECgYEAjrDrO3Fo2GvD5Jn/lER0mnxt\nIb/kvYt5WyaYutbRN1u/SKhaVeklfWzkrSZb5DkV2LOE1JXfoEgvBnms1O9OSJXw\nqDrFF7NDebw95g6JzI+SbkIHw0Cb+/E9K92FjvW3Bi8j9PKIa8c/dpwIAIirc/q8\nuhSTf4WoIOHSFbSaQPECQQD1Wi9vynJLI5lShOs0wPomZOwNrXa73Lj8ciZC4oPS\nt6tWjbLnLsP+vTSLUyEYeQGsjdbY+y5siJmAqnV/ShB9AkEA6Sgna9gQw4dXN0jB\nSjOZSjl4S2/H3wHatclrvlYfbJVU6GlIlqWGaUkdFvCuEr9iXJAY4zpEQ4P370EZ\ntsyVZQJBAOZu/X6RNSc9GBNYo0+4rzjAMLPn50wp0dPHogfPlt+hgVqZWx2l3o6y\nRVdVjA/gFqJp1Q+VWdS1tvYRIqmadkECQCVdqQuwgedEHmcewtNod42crjmwvWBx\nBKMTl6/WT4zwVb41eUujVWo0LHRLuCoK//GDqmloIh6L3MU8MqnIGb0CQFWcpD4/\nroCkMblk0hPoQPpyapJexc438x7XuEGFEhyxxauqC5R4YFKCf+KBS2gZgr4GSwBU\nQww+qZ3eRYM7faM=\n-----END PRIVATE KEY-----"; + $this->privateKeyFilePath = SSL_KEYS_PATH.'private-ne.key'; + $this->publicKeyResource = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->publicKeyString = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfdZEMQbms3t1oyAjY3kfxw/BN\n5A86fPfi4bZ97TIrIeMkMYTZegRJGm7kt6VI91gz+vgBYwVagNY937vFqru4USQz\nxzrNpAiCPi4SKr6kEy8f57zTlIVtg4pip9B7h55cCTg6tDBxSRKuUayR/phRrD/c\njBs+DMQNOBNkVW1CUQIDAQAB\n-----END PUBLIC KEY-----"; + $this->publicKeyFilePath = SSL_KEYS_PATH.'public-ne.key'; + $this->badPrivateKeyString = "-----BEGIN PRIVATE KEY-----\nfoo\nbar\n-----END PRIVATE KEY-----"; + $this->badPrivateKeyFilePath = SSL_KEYS_PATH.'nonexistant.key'; + $this->signer = new RS256(); + } + + public function testStringKeyWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKeyString); + $this->assertInternalType('bool', $this->signer->verify($this->publicKeyString, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->publicKeyString, $encrypted, 'aaa')); + } + + public function testFilePathKeyWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKeyFilePath); + $this->assertInternalType('bool', $this->signer->verify($this->publicKeyFilePath, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->publicKeyFilePath, $encrypted, 'aaa')); + } + + public function testResourceKeyWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKeyResource); + $this->assertInternalType('bool', $this->signer->verify($this->publicKeyResource, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->publicKeyResource, $encrypted, 'aaa')); + } + + /** + * @requires PHPUnit 5.4 + */ + public function testBadStringKeyThrowsException() + { + $this->expectException(\RuntimeException::class); + $this->signer->sign('aaa', $this->badPrivateKeyString); + } + + /** + * @requires PHPUnit 5.4 + */ + public function testFilePathKeyThrowsException() + { + if(defined('HHVM_VERSION')) { + // in HHVM, openssl_pkey_get_(public|private) throws an error when + // passed a file path that cannot be found + $this->expectException('PHPUnit_Framework_Error'); + } else { + $this->expectException(\RuntimeException::class); + } + $this->signer->sign('aaa', $this->badPrivateKeyFilePath); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/NoneTest.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/NoneTest.php new file mode 100644 index 0000000..171a803 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/NoneTest.php @@ -0,0 +1,24 @@ +assertTrue($signer->verify('bar', '', 'aaa')); + } + + public function testSigningWorksProperly() + { + $signer = new none(); + $signature = $signer->sign('aaa', 'foo'); + + $this->assertTrue($signature === ''); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/RS256Test.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/RS256Test.php new file mode 100644 index 0000000..e7457af --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/RS256Test.php @@ -0,0 +1,28 @@ +privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', 'tests'); + $this->public = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->signer = new RS256(); + } + + public function testVerificationWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKey); + $this->assertInternalType('bool', $this->signer->verify($this->public, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->public, $encrypted, 'aaa')); + } + + public function testSigningWorksProperly() + { + $this->assertInternalType('string', $this->signer->sign('aaa', $this->privateKey)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/RS384Test.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/RS384Test.php new file mode 100644 index 0000000..c01ed79 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/RS384Test.php @@ -0,0 +1,28 @@ +privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', 'tests'); + $this->public = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->signer = new RS384(); + } + + public function testVerificationWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKey); + $this->assertInternalType('bool', $this->signer->verify($this->public, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->public, $encrypted, 'aaa')); + } + + public function testSigningWorksProperly() + { + $this->assertInternalType('string', $this->signer->sign('aaa', $this->privateKey)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/RS512Test.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/RS512Test.php new file mode 100644 index 0000000..0c1db9f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/OpenSSL/RS512Test.php @@ -0,0 +1,28 @@ +privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', 'tests'); + $this->public = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->signer = new RS512(); + } + + public function testVerificationWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKey); + $this->assertInternalType('bool', $this->signer->verify($this->public, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->public, $encrypted, 'aaa')); + } + + public function testSigningWorksProperly() + { + $this->assertInternalType('string', $this->signer->sign('aaa', $this->privateKey)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/RS256TEST.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/RS256TEST.php new file mode 100644 index 0000000..010714d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/RS256TEST.php @@ -0,0 +1,30 @@ +privateKey = file_get_contents(SSL_KEYS_PATH.'private.key'); + $this->public = file_get_contents(SSL_KEYS_PATH.'public.key'); + $this->password = 'tests'; + $this->signer = new RS256(); + } + + public function testVerificationWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKey, $this->password); + $this->assertInternalType('bool', $this->signer->verify($this->public, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->public, $encrypted, 'aaa')); + } + + public function testSigningWorksProperly() + { + $this->assertInternalType('string', $this->signer->sign('aaa', $this->privateKey, $this->password)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/RS384Test.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/RS384Test.php new file mode 100644 index 0000000..048f2bc --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/RS384Test.php @@ -0,0 +1,30 @@ +privateKey = file_get_contents(SSL_KEYS_PATH.'private.key'); + $this->public = file_get_contents(SSL_KEYS_PATH.'public.key'); + $this->password = 'tests'; + $this->signer = new RS384(); + } + + public function testVerificationWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKey, $this->password); + $this->assertInternalType('bool', $this->signer->verify($this->public, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->public, $encrypted, 'aaa')); + } + + public function testSigningWorksProperly() + { + $this->assertInternalType('string', $this->signer->sign('aaa', $this->privateKey, $this->password)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/RS512Test.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/RS512Test.php new file mode 100644 index 0000000..e639322 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/RS512Test.php @@ -0,0 +1,30 @@ +privateKey = file_get_contents(SSL_KEYS_PATH.'private.key'); + $this->public = file_get_contents(SSL_KEYS_PATH.'public.key'); + $this->password = 'tests'; + $this->signer = new RS512(); + } + + public function testVerificationWorksProperly() + { + $encrypted = $this->signer->sign('aaa', $this->privateKey, $this->password); + $this->assertInternalType('bool', $this->signer->verify($this->public, $encrypted, 'aaa')); + $this->assertTrue($this->signer->verify($this->public, $encrypted, 'aaa')); + } + + public function testSigningWorksProperly() + { + $this->assertInternalType('string', $this->signer->sign('aaa', $this->privateKey, $this->password)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/SecLibTestCase.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/SecLibTestCase.php new file mode 100644 index 0000000..0917c60 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/Signer/SecLib/SecLibTestCase.php @@ -0,0 +1,17 @@ += 0) { + $this->markTestSkipped("phpseclib 1.0.0(LTS), even the latest 2.0.0, doesn't support PHP7 yet"); + } + + parent::setUp(); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/SimpleJWSTest.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/SimpleJWSTest.php new file mode 100644 index 0000000..cacfd81 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/Namshi/JOSE/Test/SimpleJWSTest.php @@ -0,0 +1,107 @@ + 'b', + 'exp' => $date->format('U'), + ); + $this->jws = new SimpleJWS(array('alg' => 'RS256')); + $this->jws->setPayload($data); + } + + public function testConstruction() + { + $this->assertSame($this->jws->getHeader(), array('alg' => 'RS256', 'typ' => 'JWS')); + $this->assertTrue(is_int($this->jws->getPayload()['iat']), 'iat property should be integer value (from construction)'); + } + + public function testValidationOfAValidSimpleJWS() + { + $privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', self::SSL_KEY_PASSPHRASE); + $this->jws->sign($privateKey); + + $jws = SimpleJWS::load($this->jws->getTokenString()); + $public_key = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->assertTrue($jws->isValid($public_key, 'RS256')); + } + + public function testValidationOfInvalidSimpleJWS() + { + $date = new DateTime('yesterday'); + $this->jws->setPayload(array( + 'exp' => $date->format('U'), + )); + $privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', self::SSL_KEY_PASSPHRASE); + $this->jws->sign($privateKey); + + $jws = SimpleJWS::load($this->jws->getTokenString()); + $public_key = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->assertFalse($jws->isValid($public_key, 'RS256')); + } + + public function testValidationOfValidSimpleJWSWithStringIat() + { + $date = new DateTime('tomorrow'); + $data = array( + 'a' => 'b', + 'exp' => $date->format('U'), + 'iat' => time() + ); + $this->jws->setPayload($data); + + $privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', self::SSL_KEY_PASSPHRASE); + $this->jws->sign($privateKey); + + $jws = SimpleJWS::load($this->jws->getTokenString()); + $public_key = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->assertTrue($jws->isValid($public_key, 'RS256')); + } + + public function testValidationOfValidSimpleJWSWithExpAsInt() + { + $date = new DateTime('tomorrow'); + $data = array( + 'a' => 'b', + 'exp' => $date->getTimestamp(), + 'iat' => time() + ); + $this->jws->setPayload($data); + + $privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', self::SSL_KEY_PASSPHRASE); + $this->jws->sign($privateKey); + + $jws = SimpleJWS::load($this->jws->getTokenString()); + $public_key = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->assertTrue($jws->isValid($public_key, 'RS256')); + } + + public function testValidationOfInvalidSimpleJWSWithExpAsInt() + { + $date = new DateTime('yesterday'); + $data = array( + 'a' => 'b', + 'exp' => $date->getTimestamp(), + 'iat' => time() + ); + $this->jws->setPayload($data); + + $privateKey = openssl_pkey_get_private(SSL_KEYS_PATH.'private.key', self::SSL_KEY_PASSPHRASE); + $this->jws->sign($privateKey); + + $jws = SimpleJWS::load($this->jws->getTokenString()); + $public_key = openssl_pkey_get_public(SSL_KEYS_PATH.'public.key'); + $this->assertFalse($jws->isValid($public_key, 'RS256')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/bootstrap.php b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/bootstrap.php new file mode 100644 index 0000000..b85ae41 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/bootstrap.php @@ -0,0 +1,7 @@ +add('Namshi\\JOSE\\Test', __DIR__); + +define('TEST_DIR', __DIR__); +define('SSL_KEYS_PATH', 'file://'.TEST_DIR.DIRECTORY_SEPARATOR); diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private-ne.key b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private-ne.key new file mode 100644 index 0000000..5eb9c34 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private-ne.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN91kQxBuaze3WjI +CNjeR/HD8E3kDzp89+Lhtn3tMish4yQxhNl6BEkabuS3pUj3WDP6+AFjBVqA1j3f +u8Wqu7hRJDPHOs2kCII+LhIqvqQTLx/nvNOUhW2DimKn0HuHnlwJODq0MHFJEq5R +rJH+mFGsP9yMGz4MxA04E2RVbUJRAgMBAAECgYEAjrDrO3Fo2GvD5Jn/lER0mnxt +Ib/kvYt5WyaYutbRN1u/SKhaVeklfWzkrSZb5DkV2LOE1JXfoEgvBnms1O9OSJXw +qDrFF7NDebw95g6JzI+SbkIHw0Cb+/E9K92FjvW3Bi8j9PKIa8c/dpwIAIirc/q8 +uhSTf4WoIOHSFbSaQPECQQD1Wi9vynJLI5lShOs0wPomZOwNrXa73Lj8ciZC4oPS +t6tWjbLnLsP+vTSLUyEYeQGsjdbY+y5siJmAqnV/ShB9AkEA6Sgna9gQw4dXN0jB +SjOZSjl4S2/H3wHatclrvlYfbJVU6GlIlqWGaUkdFvCuEr9iXJAY4zpEQ4P370EZ +tsyVZQJBAOZu/X6RNSc9GBNYo0+4rzjAMLPn50wp0dPHogfPlt+hgVqZWx2l3o6y +RVdVjA/gFqJp1Q+VWdS1tvYRIqmadkECQCVdqQuwgedEHmcewtNod42crjmwvWBx +BKMTl6/WT4zwVb41eUujVWo0LHRLuCoK//GDqmloIh6L3MU8MqnIGb0CQFWcpD4/ +roCkMblk0hPoQPpyapJexc438x7XuEGFEhyxxauqC5R4YFKCf+KBS2gZgr4GSwBU +Qww+qZ3eRYM7faM= +-----END PRIVATE KEY----- diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.es256.key b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.es256.key new file mode 100644 index 0000000..218a878 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.es256.key @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIKv1ZMzZ8Uxt/YxwdKpMAP0nlV7ne8gh0+5G+5Gb/tMUoAoGCCqGSM49 +AwEHoUQDQgAEvuYsP+QnrqAbM7Iyhzjt08hFSuzapyojCB/gFsBt65Wir4TYr5fS +Q96oa4qeGVeTFzl+fGiZFILootvLsiPwAQ== +-----END EC PRIVATE KEY----- diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.es384.key b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.es384.key new file mode 100644 index 0000000..f6f54e5 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.es384.key @@ -0,0 +1,6 @@ +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDClxJJett5kQ5oEizsjCpxT0z844zzVeFm44egaCZL/Y90QLBx1BxfO +/tbz6VgvRyugBwYFK4EEACKhZANiAATp/5dmyDZO+fQSgRqlD7KUxg22ybwI9/Rx +vwcjYSR9j0Gqm3dAzPCUzuZWwVGZoxlvyc6dHCamYSe8DZTzJ1L51uc+/tvBiX6r +Wo16HxamOivdU75FO3hx7Q+fbmgYZZQ= +-----END EC PRIVATE KEY----- diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.es512.key b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.es512.key new file mode 100644 index 0000000..be5d675 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.es512.key @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHbAgEBBEEWnooUpGIch1H/s8/ZUrHPo6RL+mHKhCrDO/Yjz37zM/tBJyvHmvwY +Utw3mYII0m3es3dIiAjheghBs14+UCPq8aAHBgUrgQQAI6GBiQOBhgAEAVpvo7TG +pQk5P7ZLo0qkBpaT+fFDv6HQrWElBKMxcrJd/mRNapweATsVv83YON4lTIIRXzgG +kmWeqbDr6RQO+1cSAIs+MoRmLaiPyG2xmPwQCHX2CGX/uCZiT3iOxTAJEZuUbeSA +828K4WfAA4ODdGiB87YVShhPOkiQswV3LpbpPGhC +-----END EC PRIVATE KEY----- diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.key b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.key new file mode 100644 index 0000000..2ac0b6a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/private.key @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,510C9E7AAF17A8397C4B79D906DAE432 + +W0qO1iOiS10gdomVUBbR3LdJOHRmfOmsXAjg4ezG3+Dg/0rfVkj+H3RWIpNnLq2l +ciayAqjFzLzlKYPW4/XakyhfmCrZE+mL+kFVEUjhISZ+xXLwHGltL0UeYsei/AUp +usjbxO8K0hZ1ZG2bQCEj5ff2YGmC9g1K3C7tE8XR0+QCZ/xaYkdUxDUIfYZ4MebG ++C5P+mckds6lmcdZkIZj9H+36LPH2RPlMJAdLmLGytKF37h93gcL/pgePMEY+sVj +h0YfScQ2GlE3v3S1CC1X2yjU5CtfxPHuA+2XuFIZ9twlrNFSqUWtvaCMNgSaWPLH +KdR9RC8vImz0PEu6eR4t9ytTnykYG+mujCjumeohJoWjrXJymC4ocHIa8p/EA7Hc +AWXxVlS897feG1BQ+rAiuvzIDvU8glKO8ZDjs9FUeC4O6ySCI9b4Of/57Uqo7nmQ +0nLTJntvKFeusJ9WnergOEEHg1x93n8ajM49a+eS2uEj+UlIWiT01WTVS2i5wWp7 ++wcniYwlEk36HHBWSYBmhK+Uda4isE3SBBiRBa4ETh7Goor3FcxTA5TEqKwsHG0o +1infKNmPHUy2hQTrGttoJrCpAvKq2RuQJUG5Tu5mURibihcRqCCcbyz/uKY/IIJg +9WV3gzsDXrmr2UWovD9Rfudm6mdkhz1Sn+XS69z3irMJHuW/j2sO/bO5JseurPq7 +0V9Ms2TCIlyT7ncjsV3Lf0PSmitf/W4KzRKgxKkgORHNWX4W9yLA+yMeP3CfwaBn +QiTk/dnN/uwVFQ5YlRkUsWOFxS7/gk/kBv15dTZV/1paqm0iPcExmtXqFvPlxnUr +J3NeVl6j6kOUGLPsijk4zIijVMquYug4WfjCHLmzsqEGOYoK+nA6BQwxeMSOxFWT +R8QWvvz8B6fm5BigBsUs7kQa3HcksE6YMz8dXr3r0cvINurGUpd3hDYLMdUJ0ttG +cjdHXG3+fBOhUD8zkQSpf21V1/B4df2PiFlTKar5Jx1IiplvkTDPv6Nea8zuiVzy +8Wp/PawNbPRs+KQAsr+pvged+VftvsVVGyG+0lXd7kPAJqxo4xEpD+NelHJKDgVy +uuQPMoxt1TIvCAP9jD+ENCmnGU2HhpJvngsVQs+7DviCOgbbdIfff91fyrLkSNkb +tck4q3RFpKDcKiU9yxjeAaYP6bXSq2ypwHV4YhivftyJN52TxAjGRqkuZCr5cG9P ++l3hgwTusJSjiNFkjSv7Tq3sq+s6p3+vdqBs7pS6wH/yfnJtSnPgdOkO9NqvYG67 +ALco0hSuBmKWFjr4rk9e/fVPqOFCKZNdJ44ZFViFkF1Ry/YO7XvnxCQCOk17g/aM +daMSNDJdZliGsu6lHxzF0/gq7ukTqAYJEh0Jvb7+l8/YMJZRFzxB0SENCTn9rPIY +VTrajK8z33GMHUFzbGEyoZoGxNe0F4DarHqFteBjnRLFev0N88go0hlLP0NR2hBB +RsNRTJGbzYTVZJwZTDrA11KoU3PaWFrZglsD/ExVb+OYgYv+SlbUdu9znpZBlayj +3wJv6RqhDntrbc2yPzK/27KzToNLlqdBnUO0kl64JaZukkhpDfmKJahWO4nePxvu +-----END RSA PRIVATE KEY----- diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public-ne.key b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public-ne.key new file mode 100644 index 0000000..6c5e343 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public-ne.key @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfdZEMQbms3t1oyAjY3kfxw/BN +5A86fPfi4bZ97TIrIeMkMYTZegRJGm7kt6VI91gz+vgBYwVagNY937vFqru4USQz +xzrNpAiCPi4SKr6kEy8f57zTlIVtg4pip9B7h55cCTg6tDBxSRKuUayR/phRrD/c +jBs+DMQNOBNkVW1CUQIDAQAB +-----END PUBLIC KEY----- diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.es256.key b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.es256.key new file mode 100644 index 0000000..7f33c92 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.es256.key @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvuYsP+QnrqAbM7Iyhzjt08hFSuza +pyojCB/gFsBt65Wir4TYr5fSQ96oa4qeGVeTFzl+fGiZFILootvLsiPwAQ== +-----END PUBLIC KEY----- diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.es384.key b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.es384.key new file mode 100644 index 0000000..dca6e18 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.es384.key @@ -0,0 +1,5 @@ +-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE6f+XZsg2Tvn0EoEapQ+ylMYNtsm8CPf0 +cb8HI2EkfY9Bqpt3QMzwlM7mVsFRmaMZb8nOnRwmpmEnvA2U8ydS+dbnPv7bwYl+ +q1qNeh8Wpjor3VO+RTt4ce0Pn25oGGWU +-----END PUBLIC KEY----- diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.es512.key b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.es512.key new file mode 100644 index 0000000..e0dcb04 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.es512.key @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBWm+jtMalCTk/tkujSqQGlpP58UO/ +odCtYSUEozFysl3+ZE1qnB4BOxW/zdg43iVMghFfOAaSZZ6psOvpFA77VxIAiz4y +hGYtqI/IbbGY/BAIdfYIZf+4JmJPeI7FMAkRm5Rt5IDzbwrhZ8ADg4N0aIHzthVK +GE86SJCzBXculuk8aEI= +-----END PUBLIC KEY----- diff --git a/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.key b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.key new file mode 100644 index 0000000..5029102 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/namshi/jose/tests/public.key @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtpS1ZmfVKVP5KofIhMBP +0tSWc4qlh6fm2lrZSkuKxUjEaWjzZSzs72gEIGxraWusMdoRuV54xsWRyf5KeZT0 +S+I5Prle3Idi3gICiO4NwvMk6JwSBcJWwmSLFEKyUSnB2CtfiGc0/5rQCpcEt/Dn +5iM+BNn7fqpoLIbks8rXKUIj8+qMVqkTXsEKeKinE23t1ykMldsNaaOH+hvGti5J +t2DMnH1JjoXdDXfxvSP/0gjUYb0ektudYFXoA6wekmQyJeImvgx4Myz1I4iHtkY/ +Cp7J4Mn1ejZ6HNmyvoTE/4OuY1uCeYv4UyXFc1s1uUyYtj4z57qsHGsS4dQ3A2MJ +swIDAQAB +-----END PUBLIC KEY----- diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/LICENSE b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/LICENSE new file mode 100644 index 0000000..6de45eb --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) Brian Nesbitt + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/bin/upgrade-carbon b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/bin/upgrade-carbon new file mode 100644 index 0000000..49c4c9a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/bin/upgrade-carbon @@ -0,0 +1,34 @@ +#!/usr/bin/env php +=5.3.9", + "kylekatarnls/update-helper": "^1.1", + "symfony/translation": "~2.6 || ~3.0 || ~4.0" + }, + "require-dev": { + "composer/composer": "^1.2", + "friendsofphp/php-cs-fixer": "~2", + "phpunit/phpunit": "^4.8.35 || ^5.7" + }, + "autoload": { + "psr-4": { + "": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\": "tests/" + } + }, + "config": { + "sort-packages": true + }, + "scripts": { + "test": [ + "@phpunit", + "@phpcs" + ], + "phpunit": "phpunit --verbose --coverage-clover=coverage.xml", + "phpcs": "php-cs-fixer fix -v --diff --dry-run", + "phpstan": "phpstan analyse --configuration phpstan.neon --level 3 src tests", + "post-autoload-dump": [ + "UpdateHelper\\UpdateHelper::check" + ], + "upgrade-carbon": [ + "Carbon\\Upgrade::upgrade" + ] + }, + "extra": { + "update-helper": "Carbon\\Upgrade", + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/readme.md b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/readme.md new file mode 100644 index 0000000..5e9d1cc --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/readme.md @@ -0,0 +1,94 @@ +# Carbon + +[![Latest Stable Version](https://poser.pugx.org/nesbot/carbon/v/stable.png)](https://packagist.org/packages/nesbot/carbon) +[![Total Downloads](https://poser.pugx.org/nesbot/carbon/downloads.png)](https://packagist.org/packages/nesbot/carbon) +[![Build Status](https://travis-ci.org/briannesbitt/Carbon.svg?branch=master)](https://travis-ci.org/briannesbitt/Carbon) +[![StyleCI](https://styleci.io/repos/5724990/shield?style=flat)](https://styleci.io/repos/5724990) +[![codecov.io](https://codecov.io/github/briannesbitt/Carbon/coverage.svg?branch=master)](https://codecov.io/github/briannesbitt/Carbon?branch=master) +[![PHP-Eye](https://php-eye.com/badge/nesbot/carbon/tested.svg?style=flat)](https://php-eye.com/package/nesbot/carbon) +[![PHPStan](https://img.shields.io/badge/PHPStan-enabled-brightgreen.svg?style=flat)](https://github.com/phpstan/phpstan) + +A simple PHP API extension for DateTime. [http://carbon.nesbot.com](http://carbon.nesbot.com) + +```php +use Carbon\Carbon; + +printf("Right now is %s", Carbon::now()->toDateTimeString()); +printf("Right now in Vancouver is %s", Carbon::now('America/Vancouver')); //implicit __toString() +$tomorrow = Carbon::now()->addDay(); +$lastWeek = Carbon::now()->subWeek(); +$nextSummerOlympics = Carbon::createFromDate(2016)->addYears(4); + +$officialDate = Carbon::now()->toRfc2822String(); + +$howOldAmI = Carbon::createFromDate(1975, 5, 21)->age; + +$noonTodayLondonTime = Carbon::createFromTime(12, 0, 0, 'Europe/London'); + +$internetWillBlowUpOn = Carbon::create(2038, 01, 19, 3, 14, 7, 'GMT'); + +// Don't really want this to happen so mock now +Carbon::setTestNow(Carbon::createFromDate(2000, 1, 1)); + +// comparisons are always done in UTC +if (Carbon::now()->gte($internetWillBlowUpOn)) { + die(); +} + +// Phew! Return to normal behaviour +Carbon::setTestNow(); + +if (Carbon::now()->isWeekend()) { + echo 'Party!'; +} +echo Carbon::now()->subMinutes(2)->diffForHumans(); // '2 minutes ago' + +// ... but also does 'from now', 'after' and 'before' +// rolling up to seconds, minutes, hours, days, months, years + +$daysSinceEpoch = Carbon::createFromTimestamp(0)->diffInDays(); +``` + +## Installation + +### With Composer + +``` +$ composer require nesbot/carbon +``` + +```json +{ + "require": { + "nesbot/carbon": "~1.21" + } +} +``` + +```php + + +### Without Composer + +Why are you not using [composer](http://getcomposer.org/)? Download [Carbon.php](https://github.com/briannesbitt/Carbon/blob/master/src/Carbon/Carbon.php) from the repo and save the file into your project path somewhere. + +```php + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Carbon; + +use Carbon\Exceptions\InvalidDateException; +use Closure; +use DateInterval; +use DatePeriod; +use DateTime; +use DateTimeInterface; +use DateTimeZone; +use InvalidArgumentException; +use JsonSerializable; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * A simple API extension for DateTime + * + * @property int $year + * @property int $yearIso + * @property int $month + * @property int $day + * @property int $hour + * @property int $minute + * @property int $second + * @property int $timestamp seconds since the Unix Epoch + * @property \DateTimeZone $timezone the current timezone + * @property \DateTimeZone $tz alias of timezone + * @property-read int $micro + * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday) + * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday) + * @property-read int $dayOfYear 0 through 365 + * @property-read int $weekOfMonth 1 through 5 + * @property-read int $weekNumberInMonth 1 through 5 + * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday + * @property-read int $daysInMonth number of days in the given month + * @property-read int $age does a diffInYears() with default parameters + * @property-read int $quarter the quarter of this instance, 1 - 4 + * @property-read int $offset the timezone offset in seconds from UTC + * @property-read int $offsetHours the timezone offset in hours from UTC + * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise + * @property-read bool $local checks if the timezone is local, true if local, false otherwise + * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise + * @property-read string $timezoneName + * @property-read string $tzName + * @property-read string $englishDayOfWeek the day of week in English + * @property-read string $shortEnglishDayOfWeek the abbreviated day of week in English + * @property-read string $englishMonth the day of week in English + * @property-read string $shortEnglishMonth the abbreviated day of week in English + * @property-read string $localeDayOfWeek the day of week in current locale LC_TIME + * @property-read string $shortLocaleDayOfWeek the abbreviated day of week in current locale LC_TIME + * @property-read string $localeMonth the month in current locale LC_TIME + * @property-read string $shortLocaleMonth the abbreviated month in current locale LC_TIME + */ +class Carbon extends DateTime implements JsonSerializable +{ + const NO_ZERO_DIFF = 01; + const JUST_NOW = 02; + const ONE_DAY_WORDS = 04; + const TWO_DAY_WORDS = 010; + + // Substitutes for Carbon 2 modes + const DIFF_RELATIVE_TO_NOW = 'relative-to-now'; + const DIFF_RELATIVE_TO_OTHER = 'relative-to-other'; + + /** + * The day constants. + */ + const SUNDAY = 0; + const MONDAY = 1; + const TUESDAY = 2; + const WEDNESDAY = 3; + const THURSDAY = 4; + const FRIDAY = 5; + const SATURDAY = 6; + + /** + * Names of days of the week. + * + * @var array + */ + protected static $days = array( + self::SUNDAY => 'Sunday', + self::MONDAY => 'Monday', + self::TUESDAY => 'Tuesday', + self::WEDNESDAY => 'Wednesday', + self::THURSDAY => 'Thursday', + self::FRIDAY => 'Friday', + self::SATURDAY => 'Saturday', + ); + + /** + * Number of X in Y. + */ + const YEARS_PER_MILLENNIUM = 1000; + const YEARS_PER_CENTURY = 100; + const YEARS_PER_DECADE = 10; + const MONTHS_PER_YEAR = 12; + const MONTHS_PER_QUARTER = 3; + const WEEKS_PER_YEAR = 52; + const WEEKS_PER_MONTH = 4; + const DAYS_PER_WEEK = 7; + const HOURS_PER_DAY = 24; + const MINUTES_PER_HOUR = 60; + const SECONDS_PER_MINUTE = 60; + const MICROSECONDS_PER_MILLISECOND = 1000; + const MICROSECONDS_PER_SECOND = 1000000; + + /** + * RFC7231 DateTime format. + * + * @var string + */ + const RFC7231_FORMAT = 'D, d M Y H:i:s \G\M\T'; + + /** + * Default format to use for __toString method when type juggling occurs. + * + * @var string + */ + const DEFAULT_TO_STRING_FORMAT = 'Y-m-d H:i:s'; + + /** + * Format for converting mocked time, includes microseconds. + * + * @var string + */ + const MOCK_DATETIME_FORMAT = 'Y-m-d H:i:s.u'; + + /** + * Customizable PHP_INT_SIZE override. + * + * @var int + */ + public static $PHPIntSize = PHP_INT_SIZE; + + /** + * Format to use for __toString method when type juggling occurs. + * + * @var string + */ + protected static $toStringFormat = self::DEFAULT_TO_STRING_FORMAT; + + /** + * First day of week. + * + * @var int + */ + protected static $weekStartsAt = self::MONDAY; + + /** + * Last day of week. + * + * @var int + */ + protected static $weekEndsAt = self::SUNDAY; + + /** + * Days of weekend. + * + * @var array + */ + protected static $weekendDays = array( + self::SATURDAY, + self::SUNDAY, + ); + + /** + * Midday/noon hour. + * + * @var int + */ + protected static $midDayAt = 12; + + /** + * Format regex patterns. + * + * @var array + */ + protected static $regexFormats = array( + 'd' => '(3[01]|[12][0-9]|0[1-9])', + 'D' => '([a-zA-Z]{3})', + 'j' => '([123][0-9]|[1-9])', + 'l' => '([a-zA-Z]{2,})', + 'N' => '([1-7])', + 'S' => '([a-zA-Z]{2})', + 'w' => '([0-6])', + 'z' => '(36[0-5]|3[0-5][0-9]|[12][0-9]{2}|[1-9]?[0-9])', + 'W' => '(5[012]|[1-4][0-9]|[1-9])', + 'F' => '([a-zA-Z]{2,})', + 'm' => '(1[012]|0[1-9])', + 'M' => '([a-zA-Z]{3})', + 'n' => '(1[012]|[1-9])', + 't' => '(2[89]|3[01])', + 'L' => '(0|1)', + 'o' => '([1-9][0-9]{0,4})', + 'Y' => '([1-9]?[0-9]{4})', + 'y' => '([0-9]{2})', + 'a' => '(am|pm)', + 'A' => '(AM|PM)', + 'B' => '([0-9]{3})', + 'g' => '(1[012]|[1-9])', + 'G' => '(2[0-3]|1?[0-9])', + 'h' => '(1[012]|0[1-9])', + 'H' => '(2[0-3]|[01][0-9])', + 'i' => '([0-5][0-9])', + 's' => '([0-5][0-9])', + 'u' => '([0-9]{1,6})', + 'v' => '([0-9]{1,3})', + 'e' => '([a-zA-Z]{1,5})|([a-zA-Z]*\/[a-zA-Z]*)', + 'I' => '(0|1)', + 'O' => '([\+\-](1[012]|0[0-9])[0134][05])', + 'P' => '([\+\-](1[012]|0[0-9]):[0134][05])', + 'T' => '([a-zA-Z]{1,5})', + 'Z' => '(-?[1-5]?[0-9]{1,4})', + 'U' => '([0-9]*)', + + // The formats below are combinations of the above formats. + 'c' => '(([1-9]?[0-9]{4})\-(1[012]|0[1-9])\-(3[01]|[12][0-9]|0[1-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])[\+\-](1[012]|0[0-9]):([0134][05]))', // Y-m-dTH:i:sP + 'r' => '(([a-zA-Z]{3}), ([123][0-9]|[1-9]) ([a-zA-Z]{3}) ([1-9]?[0-9]{4}) (2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]) [\+\-](1[012]|0[0-9])([0134][05]))', // D, j M Y H:i:s O + ); + + /** + * A test Carbon instance to be returned when now instances are created. + * + * @var \Carbon\Carbon + */ + protected static $testNow; + + /** + * A translator to ... er ... translate stuff. + * + * @var \Symfony\Component\Translation\TranslatorInterface + */ + protected static $translator; + + /** + * The errors that can occur. + * + * @var array + */ + protected static $lastErrors; + + /** + * The custom Carbon JSON serializer. + * + * @var callable|null + */ + protected static $serializer; + + /** + * The registered string macros. + * + * @var array + */ + protected static $localMacros = array(); + + /** + * Will UTF8 encoding be used to print localized date/time ? + * + * @var bool + */ + protected static $utf8 = false; + + /** + * Add microseconds to now on PHP < 7.1 and 7.1.3. true by default. + * + * @var bool + */ + protected static $microsecondsFallback = true; + + /** + * Indicates if months should be calculated with overflow. + * + * @var bool + */ + protected static $monthsOverflow = true; + + /** + * Indicates if years should be calculated with overflow. + * + * @var bool + */ + protected static $yearsOverflow = true; + + /** + * Indicates if years are compared with month by default so isSameMonth and isSameQuarter have $ofSameYear set + * to true by default. + * + * @var bool + */ + protected static $compareYearWithMonth = false; + + /** + * Options for diffForHumans(). + * + * @var int + */ + protected static $humanDiffOptions = self::NO_ZERO_DIFF; + + /** + * @param int $humanDiffOptions + */ + public static function setHumanDiffOptions($humanDiffOptions) + { + static::$humanDiffOptions = $humanDiffOptions; + } + + /** + * @param int $humanDiffOption + */ + public static function enableHumanDiffOption($humanDiffOption) + { + static::$humanDiffOptions = static::getHumanDiffOptions() | $humanDiffOption; + } + + /** + * @param int $humanDiffOption + */ + public static function disableHumanDiffOption($humanDiffOption) + { + static::$humanDiffOptions = static::getHumanDiffOptions() & ~$humanDiffOption; + } + + /** + * @return int + */ + public static function getHumanDiffOptions() + { + return static::$humanDiffOptions; + } + + /** + * Add microseconds to now on PHP < 7.1 and 7.1.3 if set to true, + * let microseconds to 0 on those PHP versions if false. + * + * @param bool $microsecondsFallback + */ + public static function useMicrosecondsFallback($microsecondsFallback = true) + { + static::$microsecondsFallback = $microsecondsFallback; + } + + /** + * Return true if microseconds fallback on PHP < 7.1 and 7.1.3 is + * enabled. false if disabled. + * + * @return bool + */ + public static function isMicrosecondsFallbackEnabled() + { + return static::$microsecondsFallback; + } + + /** + * Indicates if months should be calculated with overflow. + * + * @param bool $monthsOverflow + * + * @return void + */ + public static function useMonthsOverflow($monthsOverflow = true) + { + static::$monthsOverflow = $monthsOverflow; + } + + /** + * Reset the month overflow behavior. + * + * @return void + */ + public static function resetMonthsOverflow() + { + static::$monthsOverflow = true; + } + + /** + * Get the month overflow behavior. + * + * @return bool + */ + public static function shouldOverflowMonths() + { + return static::$monthsOverflow; + } + + /** + * Indicates if years should be calculated with overflow. + * + * @param bool $yearsOverflow + * + * @return void + */ + public static function useYearsOverflow($yearsOverflow = true) + { + static::$yearsOverflow = $yearsOverflow; + } + + /** + * Reset the month overflow behavior. + * + * @return void + */ + public static function resetYearsOverflow() + { + static::$yearsOverflow = true; + } + + /** + * Get the month overflow behavior. + * + * @return bool + */ + public static function shouldOverflowYears() + { + return static::$yearsOverflow; + } + + /** + * Get the month comparison default behavior. + * + * @return bool + */ + public static function compareYearWithMonth($compareYearWithMonth = true) + { + static::$compareYearWithMonth = $compareYearWithMonth; + } + + /** + * Get the month comparison default behavior. + * + * @return bool + */ + public static function shouldCompareYearWithMonth() + { + return static::$compareYearWithMonth; + } + + /** + * Creates a DateTimeZone from a string, DateTimeZone or integer offset. + * + * @param \DateTimeZone|string|int|null $object + * + * @throws \InvalidArgumentException + * + * @return \DateTimeZone + */ + protected static function safeCreateDateTimeZone($object) + { + if ($object === null) { + // Don't return null... avoid Bug #52063 in PHP <5.3.6 + return new DateTimeZone(date_default_timezone_get()); + } + + if ($object instanceof DateTimeZone) { + return $object; + } + + if (is_numeric($object)) { + $tzName = timezone_name_from_abbr(null, $object * 3600, true); + + if ($tzName === false) { + throw new InvalidArgumentException('Unknown or bad timezone ('.$object.')'); + } + + $object = $tzName; + } + + $tz = @timezone_open($object = (string) $object); + + if ($tz !== false) { + return $tz; + } + + // Work-around for a bug fixed in PHP 5.5.10 https://bugs.php.net/bug.php?id=45528 + // See: https://stackoverflow.com/q/14068594/2646927 + // @codeCoverageIgnoreStart + if (strpos($object, ':') !== false) { + try { + return static::createFromFormat('O', $object)->getTimezone(); + } catch (InvalidArgumentException $e) { + // + } + } + // @codeCoverageIgnoreEnd + + throw new InvalidArgumentException('Unknown or bad timezone ('.$object.')'); + } + + /////////////////////////////////////////////////////////////////// + //////////////////////////// CONSTRUCTORS ///////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Create a new Carbon instance. + * + * Please see the testing aids section (specifically static::setTestNow()) + * for more on the possibility of this constructor returning a test instance. + * + * @param string|null $time + * @param \DateTimeZone|string|null $tz + */ + public function __construct($time = null, $tz = null) + { + // If the class has a test now set and we are trying to create a now() + // instance then override as required + $isNow = empty($time) || $time === 'now'; + if (static::hasTestNow() && ($isNow || static::hasRelativeKeywords($time))) { + $testInstance = clone static::getTestNow(); + + //shift the time according to the given time zone + if ($tz !== null && $tz !== static::getTestNow()->getTimezone()) { + $testInstance->setTimezone($tz); + } else { + $tz = $testInstance->getTimezone(); + } + + if (static::hasRelativeKeywords($time)) { + $testInstance->modify($time); + } + + $time = $testInstance->format(static::MOCK_DATETIME_FORMAT); + } + + $timezone = static::safeCreateDateTimeZone($tz); + // @codeCoverageIgnoreStart + if ($isNow && !isset($testInstance) && static::isMicrosecondsFallbackEnabled() && ( + version_compare(PHP_VERSION, '7.1.0-dev', '<') + || + version_compare(PHP_VERSION, '7.1.3-dev', '>=') && version_compare(PHP_VERSION, '7.1.4-dev', '<') + ) + ) { + // Get microseconds from microtime() if "now" asked and PHP < 7.1 and PHP 7.1.3 if fallback enabled. + list($microTime, $timeStamp) = explode(' ', microtime()); + $dateTime = new DateTime('now', $timezone); + $dateTime->setTimestamp($timeStamp); // Use the timestamp returned by microtime as now can happen in the next second + $time = $dateTime->format(static::DEFAULT_TO_STRING_FORMAT).substr($microTime, 1, 7); + } + // @codeCoverageIgnoreEnd + + // Work-around for PHP bug https://bugs.php.net/bug.php?id=67127 + if (strpos((string) .1, '.') === false) { + $locale = setlocale(LC_NUMERIC, '0'); + setlocale(LC_NUMERIC, 'C'); + } + parent::__construct($time, $timezone); + if (isset($locale)) { + setlocale(LC_NUMERIC, $locale); + } + static::setLastErrors(parent::getLastErrors()); + } + + /** + * Create a Carbon instance from a DateTime one. + * + * @param \DateTime|\DateTimeInterface $date + * + * @return static + */ + public static function instance($date) + { + if ($date instanceof static) { + return clone $date; + } + + static::expectDateTime($date); + + return new static($date->format('Y-m-d H:i:s.u'), $date->getTimezone()); + } + + /** + * Create a carbon instance from a string. + * + * This is an alias for the constructor that allows better fluent syntax + * as it allows you to do Carbon::parse('Monday next week')->fn() rather + * than (new Carbon('Monday next week'))->fn(). + * + * @param string|null $time + * @param \DateTimeZone|string|null $tz + * + * @return static + */ + public static function parse($time = null, $tz = null) + { + return new static($time, $tz); + } + + /** + * Get a Carbon instance for the current date and time. + * + * @param \DateTimeZone|string|null $tz + * + * @return static + */ + public static function now($tz = null) + { + return new static(null, $tz); + } + + /** + * Create a Carbon instance for today. + * + * @param \DateTimeZone|string|null $tz + * + * @return static + */ + public static function today($tz = null) + { + return static::parse('today', $tz); + } + + /** + * Create a Carbon instance for tomorrow. + * + * @param \DateTimeZone|string|null $tz + * + * @return static + */ + public static function tomorrow($tz = null) + { + return static::parse('tomorrow', $tz); + } + + /** + * Create a Carbon instance for yesterday. + * + * @param \DateTimeZone|string|null $tz + * + * @return static + */ + public static function yesterday($tz = null) + { + return static::parse('yesterday', $tz); + } + + /** + * Create a Carbon instance for the greatest supported date. + * + * @return static + */ + public static function maxValue() + { + if (self::$PHPIntSize === 4) { + // 32 bit + return static::createFromTimestamp(PHP_INT_MAX); // @codeCoverageIgnore + } + + // 64 bit + return static::create(9999, 12, 31, 23, 59, 59); + } + + /** + * Create a Carbon instance for the lowest supported date. + * + * @return static + */ + public static function minValue() + { + if (self::$PHPIntSize === 4) { + // 32 bit + return static::createFromTimestamp(~PHP_INT_MAX); // @codeCoverageIgnore + } + + // 64 bit + return static::create(1, 1, 1, 0, 0, 0); + } + + /** + * Create a new Carbon instance from a specific date and time. + * + * If any of $year, $month or $day are set to null their now() values will + * be used. + * + * If $hour is null it will be set to its now() value and the default + * values for $minute and $second will be their now() values. + * + * If $hour is not null then the default values for $minute and $second + * will be 0. + * + * @param int|null $year + * @param int|null $month + * @param int|null $day + * @param int|null $hour + * @param int|null $minute + * @param int|null $second + * @param \DateTimeZone|string|null $tz + * + * @throws \InvalidArgumentException + * + * @return static + */ + public static function create($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null) + { + $now = static::hasTestNow() ? static::getTestNow() : static::now($tz); + + $defaults = array_combine(array( + 'year', + 'month', + 'day', + 'hour', + 'minute', + 'second', + ), explode('-', $now->format('Y-n-j-G-i-s'))); + + $year = $year === null ? $defaults['year'] : $year; + $month = $month === null ? $defaults['month'] : $month; + $day = $day === null ? $defaults['day'] : $day; + + if ($hour === null) { + $hour = $defaults['hour']; + $minute = $minute === null ? $defaults['minute'] : $minute; + $second = $second === null ? $defaults['second'] : $second; + } else { + $minute = $minute === null ? 0 : $minute; + $second = $second === null ? 0 : $second; + } + + $fixYear = null; + + if ($year < 0) { + $fixYear = $year; + $year = 0; + } elseif ($year > 9999) { + $fixYear = $year - 9999; + $year = 9999; + } + + $instance = static::createFromFormat('!Y-n-j G:i:s', sprintf('%s-%s-%s %s:%02s:%02s', $year, $month, $day, $hour, $minute, $second), $tz); + + if ($fixYear !== null) { + $instance->addYears($fixYear); + } + + return $instance; + } + + /** + * Create a new safe Carbon instance from a specific date and time. + * + * If any of $year, $month or $day are set to null their now() values will + * be used. + * + * If $hour is null it will be set to its now() value and the default + * values for $minute and $second will be their now() values. + * + * If $hour is not null then the default values for $minute and $second + * will be 0. + * + * If one of the set values is not valid, an \InvalidArgumentException + * will be thrown. + * + * @param int|null $year + * @param int|null $month + * @param int|null $day + * @param int|null $hour + * @param int|null $minute + * @param int|null $second + * @param \DateTimeZone|string|null $tz + * + * @throws \Carbon\Exceptions\InvalidDateException|\InvalidArgumentException + * + * @return static + */ + public static function createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null) + { + $fields = array( + 'year' => array(0, 9999), + 'month' => array(0, 12), + 'day' => array(0, 31), + 'hour' => array(0, 24), + 'minute' => array(0, 59), + 'second' => array(0, 59), + ); + + foreach ($fields as $field => $range) { + if ($$field !== null && (!is_int($$field) || $$field < $range[0] || $$field > $range[1])) { + throw new InvalidDateException($field, $$field); + } + } + + $instance = static::create($year, $month, $day, $hour, $minute, $second, $tz); + + foreach (array_reverse($fields) as $field => $range) { + if ($$field !== null && (!is_int($$field) || $$field !== $instance->$field)) { + throw new InvalidDateException($field, $$field); + } + } + + return $instance; + } + + /** + * Create a Carbon instance from just a date. The time portion is set to now. + * + * @param int|null $year + * @param int|null $month + * @param int|null $day + * @param \DateTimeZone|string|null $tz + * + * @throws \InvalidArgumentException + * + * @return static + */ + public static function createFromDate($year = null, $month = null, $day = null, $tz = null) + { + return static::create($year, $month, $day, null, null, null, $tz); + } + + /** + * Create a Carbon instance from just a date. The time portion is set to midnight. + * + * @param int|null $year + * @param int|null $month + * @param int|null $day + * @param \DateTimeZone|string|null $tz + * + * @return static + */ + public static function createMidnightDate($year = null, $month = null, $day = null, $tz = null) + { + return static::create($year, $month, $day, 0, 0, 0, $tz); + } + + /** + * Create a Carbon instance from just a time. The date portion is set to today. + * + * @param int|null $hour + * @param int|null $minute + * @param int|null $second + * @param \DateTimeZone|string|null $tz + * + * @throws \InvalidArgumentException + * + * @return static + */ + public static function createFromTime($hour = null, $minute = null, $second = null, $tz = null) + { + return static::create(null, null, null, $hour, $minute, $second, $tz); + } + + /** + * Create a Carbon instance from a time string. The date portion is set to today. + * + * @param string $time + * @param \DateTimeZone|string|null $tz + * + * @throws \InvalidArgumentException + * + * @return static + */ + public static function createFromTimeString($time, $tz = null) + { + return static::today($tz)->setTimeFromTimeString($time); + } + + private static function createFromFormatAndTimezone($format, $time, $tz) + { + return $tz !== null + ? parent::createFromFormat($format, $time, static::safeCreateDateTimeZone($tz)) + : parent::createFromFormat($format, $time); + } + + /** + * Create a Carbon instance from a specific format. + * + * @param string $format Datetime format + * @param string $time + * @param \DateTimeZone|string|null $tz + * + * @throws InvalidArgumentException + * + * @return static + */ + public static function createFromFormat($format, $time, $tz = null) + { + // First attempt to create an instance, so that error messages are based on the unmodified format. + $date = self::createFromFormatAndTimezone($format, $time, $tz); + $lastErrors = parent::getLastErrors(); + + if (($mock = static::getTestNow()) && ($date instanceof DateTime || $date instanceof DateTimeInterface)) { + // Set timezone from mock if custom timezone was neither given directly nor as a part of format. + // First let's skip the part that will be ignored by the parser. + $nonEscaped = '(?getTimezone(); + } + + // Prepend mock datetime only if the format does not contain non escaped unix epoch reset flag. + if (!preg_match("/{$nonEscaped}[!|]/", $format)) { + $format = static::MOCK_DATETIME_FORMAT.' '.$format; + $time = $mock->format(static::MOCK_DATETIME_FORMAT).' '.$time; + } + + // Regenerate date from the modified format to base result on the mocked instance instead of now. + $date = self::createFromFormatAndTimezone($format, $time, $tz); + } + + if ($date instanceof DateTime || $date instanceof DateTimeInterface) { + $instance = static::instance($date); + $instance::setLastErrors($lastErrors); + + return $instance; + } + + throw new InvalidArgumentException(implode(PHP_EOL, $lastErrors['errors'])); + } + + /** + * Set last errors. + * + * @param array $lastErrors + * + * @return void + */ + private static function setLastErrors(array $lastErrors) + { + static::$lastErrors = $lastErrors; + } + + /** + * {@inheritdoc} + */ + public static function getLastErrors() + { + return static::$lastErrors; + } + + /** + * Create a Carbon instance from a timestamp. + * + * @param int $timestamp + * @param \DateTimeZone|string|null $tz + * + * @return static + */ + public static function createFromTimestamp($timestamp, $tz = null) + { + return static::today($tz)->setTimestamp($timestamp); + } + + /** + * Create a Carbon instance from a timestamp in milliseconds. + * + * @param int $timestamp + * @param \DateTimeZone|string|null $tz + * + * @return static + */ + public static function createFromTimestampMs($timestamp, $tz = null) + { + return static::createFromFormat('U.u', sprintf('%F', $timestamp / 1000)) + ->setTimezone($tz); + } + + /** + * Create a Carbon instance from an UTC timestamp. + * + * @param int $timestamp + * + * @return static + */ + public static function createFromTimestampUTC($timestamp) + { + return new static('@'.$timestamp); + } + + /** + * Make a Carbon instance from given variable if possible. + * + * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals + * and recurrences). Throw an exception for invalid format, but otherwise return null. + * + * @param mixed $var + * + * @return static|null + */ + public static function make($var) + { + if ($var instanceof DateTime || $var instanceof DateTimeInterface) { + return static::instance($var); + } + + if (is_string($var)) { + $var = trim($var); + $first = substr($var, 0, 1); + + if (is_string($var) && $first !== 'P' && $first !== 'R' && preg_match('/[a-z0-9]/i', $var)) { + return static::parse($var); + } + } + } + + /** + * Get a copy of the instance. + * + * @return static + */ + public function copy() + { + return clone $this; + } + + /** + * Returns a present instance in the same timezone. + * + * @return static + */ + public function nowWithSameTz() + { + return static::now($this->getTimezone()); + } + + /** + * Throws an exception if the given object is not a DateTime and does not implement DateTimeInterface + * and not in $other. + * + * @param mixed $date + * @param string|array $other + * + * @throws \InvalidArgumentException + */ + protected static function expectDateTime($date, $other = array()) + { + $message = 'Expected '; + foreach ((array) $other as $expect) { + $message .= "{$expect}, "; + } + + if (!$date instanceof DateTime && !$date instanceof DateTimeInterface) { + throw new InvalidArgumentException( + $message.'DateTime or DateTimeInterface, '. + (is_object($date) ? get_class($date) : gettype($date)).' given' + ); + } + } + + /** + * Return the Carbon instance passed through, a now instance in the same timezone + * if null given or parse the input if string given. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * + * @return static + */ + protected function resolveCarbon($date = null) + { + if (!$date) { + return $this->nowWithSameTz(); + } + + if (is_string($date)) { + return static::parse($date, $this->getTimezone()); + } + + static::expectDateTime($date, array('null', 'string')); + + return $date instanceof self ? $date : static::instance($date); + } + + /////////////////////////////////////////////////////////////////// + ///////////////////////// GETTERS AND SETTERS ///////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Get a part of the Carbon object + * + * @param string $name + * + * @throws \InvalidArgumentException + * + * @return string|int|bool|\DateTimeZone + */ + public function __get($name) + { + static $formats = array( + 'year' => 'Y', + 'yearIso' => 'o', + 'month' => 'n', + 'day' => 'j', + 'hour' => 'G', + 'minute' => 'i', + 'second' => 's', + 'micro' => 'u', + 'dayOfWeek' => 'w', + 'dayOfWeekIso' => 'N', + 'dayOfYear' => 'z', + 'weekOfYear' => 'W', + 'daysInMonth' => 't', + 'timestamp' => 'U', + 'englishDayOfWeek' => 'l', + 'shortEnglishDayOfWeek' => 'D', + 'englishMonth' => 'F', + 'shortEnglishMonth' => 'M', + 'localeDayOfWeek' => '%A', + 'shortLocaleDayOfWeek' => '%a', + 'localeMonth' => '%B', + 'shortLocaleMonth' => '%b', + ); + + switch (true) { + case isset($formats[$name]): + $format = $formats[$name]; + $method = substr($format, 0, 1) === '%' ? 'formatLocalized' : 'format'; + $value = $this->$method($format); + + return is_numeric($value) ? (int) $value : $value; + + case $name === 'weekOfMonth': + return (int) ceil($this->day / static::DAYS_PER_WEEK); + + case $name === 'weekNumberInMonth': + return (int) ceil(($this->day + $this->copy()->startOfMonth()->dayOfWeek - 1) / static::DAYS_PER_WEEK); + + case $name === 'age': + return $this->diffInYears(); + + case $name === 'quarter': + return (int) ceil($this->month / static::MONTHS_PER_QUARTER); + + case $name === 'offset': + return $this->getOffset(); + + case $name === 'offsetHours': + return $this->getOffset() / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR; + + case $name === 'dst': + return $this->format('I') === '1'; + + case $name === 'local': + return $this->getOffset() === $this->copy()->setTimezone(date_default_timezone_get())->getOffset(); + + case $name === 'utc': + return $this->getOffset() === 0; + + case $name === 'timezone' || $name === 'tz': + return $this->getTimezone(); + + case $name === 'timezoneName' || $name === 'tzName': + return $this->getTimezone()->getName(); + + default: + throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name)); + } + } + + /** + * Check if an attribute exists on the object + * + * @param string $name + * + * @return bool + */ + public function __isset($name) + { + try { + $this->__get($name); + } catch (InvalidArgumentException $e) { + return false; + } + + return true; + } + + /** + * Set a part of the Carbon object + * + * @param string $name + * @param string|int|\DateTimeZone $value + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function __set($name, $value) + { + switch ($name) { + case 'year': + case 'month': + case 'day': + case 'hour': + case 'minute': + case 'second': + list($year, $month, $day, $hour, $minute, $second) = explode('-', $this->format('Y-n-j-G-i-s')); + $$name = $value; + $this->setDateTime($year, $month, $day, $hour, $minute, $second); + break; + + case 'timestamp': + parent::setTimestamp($value); + break; + + case 'timezone': + case 'tz': + $this->setTimezone($value); + break; + + default: + throw new InvalidArgumentException(sprintf("Unknown setter '%s'", $name)); + } + } + + /** + * Set the instance's year + * + * @param int $value + * + * @return static + */ + public function year($value) + { + $this->year = $value; + + return $this; + } + + /** + * Set the instance's month + * + * @param int $value + * + * @return static + */ + public function month($value) + { + $this->month = $value; + + return $this; + } + + /** + * Set the instance's day + * + * @param int $value + * + * @return static + */ + public function day($value) + { + $this->day = $value; + + return $this; + } + + /** + * Set the instance's hour + * + * @param int $value + * + * @return static + */ + public function hour($value) + { + $this->hour = $value; + + return $this; + } + + /** + * Set the instance's minute + * + * @param int $value + * + * @return static + */ + public function minute($value) + { + $this->minute = $value; + + return $this; + } + + /** + * Set the instance's second + * + * @param int $value + * + * @return static + */ + public function second($value) + { + $this->second = $value; + + return $this; + } + + /** + * Sets the current date of the DateTime object to a different date. + * Calls modify as a workaround for a php bug + * + * @param int $year + * @param int $month + * @param int $day + * + * @return static + * + * @see https://github.com/briannesbitt/Carbon/issues/539 + * @see https://bugs.php.net/bug.php?id=63863 + */ + public function setDate($year, $month, $day) + { + $this->modify('+0 day'); + + return parent::setDate($year, $month, $day); + } + + /** + * Set the date and time all together + * + * @param int $year + * @param int $month + * @param int $day + * @param int $hour + * @param int $minute + * @param int $second + * + * @return static + */ + public function setDateTime($year, $month, $day, $hour, $minute, $second = 0) + { + return $this->setDate($year, $month, $day)->setTime($hour, $minute, $second); + } + + /** + * Set the time by time string + * + * @param string $time + * + * @return static + */ + public function setTimeFromTimeString($time) + { + if (strpos($time, ':') === false) { + $time .= ':0'; + } + + return $this->modify($time); + } + + /** + * Set the instance's timestamp + * + * @param int $value + * + * @return static + */ + public function timestamp($value) + { + return $this->setTimestamp($value); + } + + /** + * Alias for setTimezone() + * + * @param \DateTimeZone|string $value + * + * @return static + */ + public function timezone($value) + { + return $this->setTimezone($value); + } + + /** + * Alias for setTimezone() + * + * @param \DateTimeZone|string $value + * + * @return static + */ + public function tz($value) + { + return $this->setTimezone($value); + } + + /** + * Set the instance's timezone from a string or object + * + * @param \DateTimeZone|string $value + * + * @return static + */ + public function setTimezone($value) + { + parent::setTimezone(static::safeCreateDateTimeZone($value)); + // https://bugs.php.net/bug.php?id=72338 + // just workaround on this bug + $this->getTimestamp(); + + return $this; + } + + /** + * Set the year, month, and date for this instance to that of the passed instance. + * + * @param \Carbon\Carbon|\DateTimeInterface $date + * + * @return static + */ + public function setDateFrom($date) + { + $date = static::instance($date); + + $this->setDate($date->year, $date->month, $date->day); + + return $this; + } + + /** + * Set the hour, day, and time for this instance to that of the passed instance. + * + * @param \Carbon\Carbon|\DateTimeInterface $date + * + * @return static + */ + public function setTimeFrom($date) + { + $date = static::instance($date); + + $this->setTime($date->hour, $date->minute, $date->second); + + return $this; + } + + /** + * Get the days of the week + * + * @return array + */ + public static function getDays() + { + return static::$days; + } + + /////////////////////////////////////////////////////////////////// + /////////////////////// WEEK SPECIAL DAYS ///////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Get the first day of week + * + * @return int + */ + public static function getWeekStartsAt() + { + return static::$weekStartsAt; + } + + /** + * Set the first day of week + * + * @param int $day week start day + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function setWeekStartsAt($day) + { + if ($day > static::SATURDAY || $day < static::SUNDAY) { + throw new InvalidArgumentException('Day of a week should be greater than or equal to 0 and less than or equal to 6.'); + } + + static::$weekStartsAt = $day; + } + + /** + * Get the last day of week + * + * @return int + */ + public static function getWeekEndsAt() + { + return static::$weekEndsAt; + } + + /** + * Set the last day of week + * + * @param int $day + * + * @throws InvalidArgumentException + * + * @return void + */ + public static function setWeekEndsAt($day) + { + if ($day > static::SATURDAY || $day < static::SUNDAY) { + throw new InvalidArgumentException('Day of a week should be greater than or equal to 0 and less than or equal to 6.'); + } + + static::$weekEndsAt = $day; + } + + /** + * Get weekend days + * + * @return array + */ + public static function getWeekendDays() + { + return static::$weekendDays; + } + + /** + * Set weekend days + * + * @param array $days + * + * @return void + */ + public static function setWeekendDays($days) + { + static::$weekendDays = $days; + } + + /** + * get midday/noon hour + * + * @return int + */ + public static function getMidDayAt() + { + return static::$midDayAt; + } + + /** + * Set midday/noon hour + * + * @param int $hour midday hour + * + * @return void + */ + public static function setMidDayAt($hour) + { + static::$midDayAt = $hour; + } + + /////////////////////////////////////////////////////////////////// + ///////////////////////// TESTING AIDS //////////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Set a Carbon instance (real or mock) to be returned when a "now" + * instance is created. The provided instance will be returned + * specifically under the following conditions: + * - A call to the static now() method, ex. Carbon::now() + * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null) + * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now') + * - When a string containing the desired time is passed to Carbon::parse(). + * + * Note the timezone parameter was left out of the examples above and + * has no affect as the mock value will be returned regardless of its value. + * + * To clear the test instance call this method using the default + * parameter of null. + * + * @param \Carbon\Carbon|null $testNow real or mock Carbon instance + * @param \Carbon\Carbon|string|null $testNow + */ + public static function setTestNow($testNow = null) + { + static::$testNow = is_string($testNow) ? static::parse($testNow) : $testNow; + } + + /** + * Get the Carbon instance (real or mock) to be returned when a "now" + * instance is created. + * + * @return static the current instance used for testing + */ + public static function getTestNow() + { + return static::$testNow; + } + + /** + * Determine if there is a valid test instance set. A valid test instance + * is anything that is not null. + * + * @return bool true if there is a test instance, otherwise false + */ + public static function hasTestNow() + { + return static::getTestNow() !== null; + } + + /** + * Determine if a time string will produce a relative date. + * + * @param string $time + * + * @return bool true if time match a relative date, false if absolute or invalid time string + */ + public static function hasRelativeKeywords($time) + { + if (strtotime($time) === false) { + return false; + } + + $date1 = new DateTime('2000-01-01T00:00:00Z'); + $date1->modify($time); + $date2 = new DateTime('2001-12-25T00:00:00Z'); + $date2->modify($time); + + return $date1 != $date2; + } + + /////////////////////////////////////////////////////////////////// + /////////////////////// LOCALIZATION ////////////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Initialize the translator instance if necessary. + * + * @return \Symfony\Component\Translation\TranslatorInterface + */ + protected static function translator() + { + if (static::$translator === null) { + static::$translator = Translator::get(); + } + + return static::$translator; + } + + /** + * Get the translator instance in use + * + * @return \Symfony\Component\Translation\TranslatorInterface + */ + public static function getTranslator() + { + return static::translator(); + } + + /** + * Set the translator instance to use + * + * @param \Symfony\Component\Translation\TranslatorInterface $translator + * + * @return void + */ + public static function setTranslator(TranslatorInterface $translator) + { + static::$translator = $translator; + } + + /** + * Get the current translator locale + * + * @return string + */ + public static function getLocale() + { + return static::translator()->getLocale(); + } + + /** + * Set the current translator locale and indicate if the source locale file exists + * + * @param string $locale locale ex. en + * + * @return bool + */ + public static function setLocale($locale) + { + return static::translator()->setLocale($locale) !== false; + } + + /** + * Set the current locale to the given, execute the passed function, reset the locale to previous one, + * then return the result of the closure (or null if the closure was void). + * + * @param string $locale locale ex. en + * + * @return mixed + */ + public static function executeWithLocale($locale, $func) + { + $currentLocale = static::getLocale(); + $result = call_user_func($func, static::setLocale($locale) ? static::getLocale() : false, static::translator()); + static::setLocale($currentLocale); + + return $result; + } + + /** + * Returns true if the given locale is internally supported and has short-units support. + * Support is considered enabled if either year, day or hour has a short variant translated. + * + * @param string $locale locale ex. en + * + * @return bool + */ + public static function localeHasShortUnits($locale) + { + return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { + return $newLocale && + ( + ($y = $translator->trans('y')) !== 'y' && + $y !== $translator->trans('year') + ) || ( + ($y = $translator->trans('d')) !== 'd' && + $y !== $translator->trans('day') + ) || ( + ($y = $translator->trans('h')) !== 'h' && + $y !== $translator->trans('hour') + ); + }); + } + + /** + * Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after). + * Support is considered enabled if the 4 sentences are translated in the given locale. + * + * @param string $locale locale ex. en + * + * @return bool + */ + public static function localeHasDiffSyntax($locale) + { + return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { + return $newLocale && + $translator->trans('ago') !== 'ago' && + $translator->trans('from_now') !== 'from_now' && + $translator->trans('before') !== 'before' && + $translator->trans('after') !== 'after'; + }); + } + + /** + * Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow). + * Support is considered enabled if the 3 words are translated in the given locale. + * + * @param string $locale locale ex. en + * + * @return bool + */ + public static function localeHasDiffOneDayWords($locale) + { + return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { + return $newLocale && + $translator->trans('diff_now') !== 'diff_now' && + $translator->trans('diff_yesterday') !== 'diff_yesterday' && + $translator->trans('diff_tomorrow') !== 'diff_tomorrow'; + }); + } + + /** + * Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow). + * Support is considered enabled if the 2 words are translated in the given locale. + * + * @param string $locale locale ex. en + * + * @return bool + */ + public static function localeHasDiffTwoDayWords($locale) + { + return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { + return $newLocale && + $translator->trans('diff_before_yesterday') !== 'diff_before_yesterday' && + $translator->trans('diff_after_tomorrow') !== 'diff_after_tomorrow'; + }); + } + + /** + * Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X). + * Support is considered enabled if the 4 sentences are translated in the given locale. + * + * @param string $locale locale ex. en + * + * @return bool + */ + public static function localeHasPeriodSyntax($locale) + { + return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) { + return $newLocale && + $translator->trans('period_recurrences') !== 'period_recurrences' && + $translator->trans('period_interval') !== 'period_interval' && + $translator->trans('period_start_date') !== 'period_start_date' && + $translator->trans('period_end_date') !== 'period_end_date'; + }); + } + + /** + * Returns the list of internally available locales and already loaded custom locales. + * (It will ignore custom translator dynamic loading.) + * + * @return array + */ + public static function getAvailableLocales() + { + $translator = static::translator(); + $locales = array(); + if ($translator instanceof Translator) { + foreach (glob(__DIR__.'/Lang/*.php') as $file) { + $locales[] = substr($file, strrpos($file, '/') + 1, -4); + } + + $locales = array_unique(array_merge($locales, array_keys($translator->getMessages()))); + } + + return $locales; + } + + /////////////////////////////////////////////////////////////////// + /////////////////////// STRING FORMATTING ///////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Set if UTF8 will be used for localized date/time + * + * @param bool $utf8 + */ + public static function setUtf8($utf8) + { + static::$utf8 = $utf8; + } + + /** + * Format the instance with the current locale. You can set the current + * locale using setlocale() http://php.net/setlocale. + * + * @param string $format + * + * @return string + */ + public function formatLocalized($format) + { + // Check for Windows to find and replace the %e modifier correctly. + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { + $format = preg_replace('#(?toDateTimeString())); + + return static::$utf8 ? utf8_encode($formatted) : $formatted; + } + + /** + * Reset the format used to the default when type juggling a Carbon instance to a string + * + * @return void + */ + public static function resetToStringFormat() + { + static::setToStringFormat(static::DEFAULT_TO_STRING_FORMAT); + } + + /** + * Set the default format used when type juggling a Carbon instance to a string + * + * @param string|Closure $format + * + * @return void + */ + public static function setToStringFormat($format) + { + static::$toStringFormat = $format; + } + + /** + * Format the instance as a string using the set format + * + * @return string + */ + public function __toString() + { + $format = static::$toStringFormat; + + return $this->format($format instanceof Closure ? $format($this) : $format); + } + + /** + * Format the instance as date + * + * @return string + */ + public function toDateString() + { + return $this->format('Y-m-d'); + } + + /** + * Format the instance as a readable date + * + * @return string + */ + public function toFormattedDateString() + { + return $this->format('M j, Y'); + } + + /** + * Format the instance as time + * + * @return string + */ + public function toTimeString() + { + return $this->format('H:i:s'); + } + + /** + * Format the instance as date and time + * + * @return string + */ + public function toDateTimeString() + { + return $this->format('Y-m-d H:i:s'); + } + + /** + * Format the instance as date and time T-separated with no timezone + * + * @example + * ``` + * echo Carbon::now()->toDateTimeLocalString(); + * ``` + * + * @return string + */ + public function toDateTimeLocalString() + { + return $this->format('Y-m-d\TH:i:s'); + } + + /** + * Format the instance with day, date and time + * + * @return string + */ + public function toDayDateTimeString() + { + return $this->format('D, M j, Y g:i A'); + } + + /** + * Format the instance as ATOM + * + * @return string + */ + public function toAtomString() + { + return $this->format(static::ATOM); + } + + /** + * Format the instance as COOKIE + * + * @return string + */ + public function toCookieString() + { + return $this->format(static::COOKIE); + } + + /** + * Format the instance as ISO8601 + * + * @return string + */ + public function toIso8601String() + { + return $this->toAtomString(); + } + + /** + * Format the instance as RFC822 + * + * @return string + */ + public function toRfc822String() + { + return $this->format(static::RFC822); + } + + /** + * Convert the instance to UTC and return as Zulu ISO8601 + * + * @return string + */ + public function toIso8601ZuluString() + { + return $this->copy()->setTimezone('UTC')->format('Y-m-d\TH:i:s\Z'); + } + + /** + * Format the instance as RFC850 + * + * @return string + */ + public function toRfc850String() + { + return $this->format(static::RFC850); + } + + /** + * Format the instance as RFC1036 + * + * @return string + */ + public function toRfc1036String() + { + return $this->format(static::RFC1036); + } + + /** + * Format the instance as RFC1123 + * + * @return string + */ + public function toRfc1123String() + { + return $this->format(static::RFC1123); + } + + /** + * Format the instance as RFC2822 + * + * @return string + */ + public function toRfc2822String() + { + return $this->format(static::RFC2822); + } + + /** + * Format the instance as RFC3339 + * + * @return string + */ + public function toRfc3339String() + { + return $this->format(static::RFC3339); + } + + /** + * Format the instance as RSS + * + * @return string + */ + public function toRssString() + { + return $this->format(static::RSS); + } + + /** + * Format the instance as W3C + * + * @return string + */ + public function toW3cString() + { + return $this->format(static::W3C); + } + + /** + * Format the instance as RFC7231 + * + * @return string + */ + public function toRfc7231String() + { + return $this->copy() + ->setTimezone('GMT') + ->format(static::RFC7231_FORMAT); + } + + /** + * Get default array representation + * + * @return array + */ + public function toArray() + { + return array( + 'year' => $this->year, + 'month' => $this->month, + 'day' => $this->day, + 'dayOfWeek' => $this->dayOfWeek, + 'dayOfYear' => $this->dayOfYear, + 'hour' => $this->hour, + 'minute' => $this->minute, + 'second' => $this->second, + 'micro' => $this->micro, + 'timestamp' => $this->timestamp, + 'formatted' => $this->format(self::DEFAULT_TO_STRING_FORMAT), + 'timezone' => $this->timezone, + ); + } + + /** + * Get default object representation. + * + * @example + * ``` + * var_dump(Carbon::now()->toObject()); + * ``` + * + * @return object + */ + public function toObject() + { + return (object) $this->toArray(); + } + + /** + * Returns english human readable complete date string. + * + * @example + * ``` + * echo Carbon::now()->toString(); + * ``` + * + * @return string + */ + public function toString() + { + return $this->format('D M j Y H:i:s \G\M\TO'); + } + + /** + * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z, if $keepOffset truthy, offset will be kept: + * 1977-04-22T01:00:00-05:00). + * + * @example + * ``` + * echo Carbon::now('America/Toronto')->toISOString() . "\n"; + * echo Carbon::now('America/Toronto')->toISOString(true) . "\n"; + * ``` + * + * @param bool $keepOffset Pass true to keep the date offset. Else forced to UTC. + * + * @return null|string + */ + public function toISOString($keepOffset = false) + { + if ($this->year === 0) { + return null; + } + + $year = $this->year < 0 || $this->year > 9999 + ? ($this->year < 0 ? '-' : '+').str_pad(abs($this->year), 6, '0', STR_PAD_LEFT) + : str_pad($this->year, 4, '0', STR_PAD_LEFT); + $tz = $keepOffset ? $this->format('P') : 'Z'; + $date = $keepOffset ? $this : $this->copy()->setTimezone('UTC'); + + return $year.$date->format('-m-d\TH:i:s.u').$tz; + } + + /** + * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z) with UTC timezone. + * + * @example + * ``` + * echo Carbon::now('America/Toronto')->toJSON(); + * ``` + * + * @return null|string + */ + public function toJSON() + { + return $this->toISOString(); + } + + /** + * Return native DateTime PHP object matching the current instance. + * + * @example + * ``` + * var_dump(Carbon::now()->toDateTime()); + * ``` + * + * @return DateTime + */ + public function toDateTime() + { + return new DateTime($this->format('Y-m-d H:i:s.u'), $this->getTimezone()); + } + + /** + * @alias toDateTime + * + * Return native DateTime PHP object matching the current instance. + * + * @example + * ``` + * var_dump(Carbon::now()->toDate()); + * ``` + * + * @return DateTime + */ + public function toDate() + { + return $this->toDateTime(); + } + + /////////////////////////////////////////////////////////////////// + ////////////////////////// COMPARISONS //////////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Determines if the instance is equal to another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @return bool + */ + public function eq($date) + { + return $this == $date; + } + + /** + * Determines if the instance is equal to another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @see eq() + * + * @return bool + */ + public function equalTo($date) + { + return $this->eq($date); + } + + /** + * Determines if the instance is not equal to another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @return bool + */ + public function ne($date) + { + return !$this->eq($date); + } + + /** + * Determines if the instance is not equal to another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @see ne() + * + * @return bool + */ + public function notEqualTo($date) + { + return $this->ne($date); + } + + /** + * Determines if the instance is greater (after) than another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @return bool + */ + public function gt($date) + { + return $this > $date; + } + + /** + * Determines if the instance is greater (after) than another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @see gt() + * + * @return bool + */ + public function greaterThan($date) + { + return $this->gt($date); + } + + /** + * Determines if the instance is greater (after) than another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @see gt() + * + * @return bool + */ + public function isAfter($date) + { + return $this->gt($date); + } + + /** + * Determines if the instance is greater (after) than or equal to another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @return bool + */ + public function gte($date) + { + return $this >= $date; + } + + /** + * Determines if the instance is greater (after) than or equal to another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @see gte() + * + * @return bool + */ + public function greaterThanOrEqualTo($date) + { + return $this->gte($date); + } + + /** + * Determines if the instance is less (before) than another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @return bool + */ + public function lt($date) + { + return $this < $date; + } + + /** + * Determines if the instance is less (before) than another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @see lt() + * + * @return bool + */ + public function lessThan($date) + { + return $this->lt($date); + } + + /** + * Determines if the instance is less (before) than another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @see lt() + * + * @return bool + */ + public function isBefore($date) + { + return $this->lt($date); + } + + /** + * Determines if the instance is less (before) or equal to another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @return bool + */ + public function lte($date) + { + return $this <= $date; + } + + /** + * Determines if the instance is less (before) or equal to another + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @see lte() + * + * @return bool + */ + public function lessThanOrEqualTo($date) + { + return $this->lte($date); + } + + /** + * Determines if the instance is between two others + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 + * @param bool $equal Indicates if an equal to comparison should be done + * + * @return bool + */ + public function between($date1, $date2, $equal = true) + { + if ($date1->gt($date2)) { + $temp = $date1; + $date1 = $date2; + $date2 = $temp; + } + + if ($equal) { + return $this->gte($date1) && $this->lte($date2); + } + + return $this->gt($date1) && $this->lt($date2); + } + + protected function floatDiffInSeconds($date) + { + $date = $this->resolveCarbon($date); + + return abs($this->diffInRealSeconds($date, false) + ($date->micro - $this->micro) / 1000000); + } + + /** + * Determines if the instance is between two others + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 + * @param bool $equal Indicates if a > and < comparison should be used or <= or >= + * + * @return bool + */ + public function isBetween($date1, $date2, $equal = true) + { + return $this->between($date1, $date2, $equal); + } + + /** + * Get the closest date from the instance. + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 + * + * @return static + */ + public function closest($date1, $date2) + { + return $this->floatDiffInSeconds($date1) < $this->floatDiffInSeconds($date2) ? $date1 : $date2; + } + + /** + * Get the farthest date from the instance. + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1 + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2 + * + * @return static + */ + public function farthest($date1, $date2) + { + return $this->floatDiffInSeconds($date1) > $this->floatDiffInSeconds($date2) ? $date1 : $date2; + } + + /** + * Get the minimum instance between a given instance (default now) and the current instance. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * + * @return static + */ + public function min($date = null) + { + $date = $this->resolveCarbon($date); + + return $this->lt($date) ? $this : $date; + } + + /** + * Get the minimum instance between a given instance (default now) and the current instance. + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @see min() + * + * @return static + */ + public function minimum($date = null) + { + return $this->min($date); + } + + /** + * Get the maximum instance between a given instance (default now) and the current instance. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * + * @return static + */ + public function max($date = null) + { + $date = $this->resolveCarbon($date); + + return $this->gt($date) ? $this : $date; + } + + /** + * Get the maximum instance between a given instance (default now) and the current instance. + * + * @param \Carbon\Carbon|\DateTimeInterface|mixed $date + * + * @see max() + * + * @return static + */ + public function maximum($date = null) + { + return $this->max($date); + } + + /** + * Determines if the instance is a weekday. + * + * @return bool + */ + public function isWeekday() + { + return !$this->isWeekend(); + } + + /** + * Determines if the instance is a weekend day. + * + * @return bool + */ + public function isWeekend() + { + return in_array($this->dayOfWeek, static::$weekendDays); + } + + /** + * Determines if the instance is yesterday. + * + * @return bool + */ + public function isYesterday() + { + return $this->toDateString() === static::yesterday($this->getTimezone())->toDateString(); + } + + /** + * Determines if the instance is today. + * + * @return bool + */ + public function isToday() + { + return $this->toDateString() === $this->nowWithSameTz()->toDateString(); + } + + /** + * Determines if the instance is tomorrow. + * + * @return bool + */ + public function isTomorrow() + { + return $this->toDateString() === static::tomorrow($this->getTimezone())->toDateString(); + } + + /** + * Determines if the instance is within the next week. + * + * @return bool + */ + public function isNextWeek() + { + return $this->weekOfYear === $this->nowWithSameTz()->addWeek()->weekOfYear; + } + + /** + * Determines if the instance is within the last week. + * + * @return bool + */ + public function isLastWeek() + { + return $this->weekOfYear === $this->nowWithSameTz()->subWeek()->weekOfYear; + } + + /** + * Determines if the instance is within the next quarter. + * + * @return bool + */ + public function isNextQuarter() + { + return $this->quarter === $this->nowWithSameTz()->addQuarter()->quarter; + } + + /** + * Determines if the instance is within the last quarter. + * + * @return bool + */ + public function isLastQuarter() + { + return $this->quarter === $this->nowWithSameTz()->subQuarter()->quarter; + } + + /** + * Determines if the instance is within the next month. + * + * @return bool + */ + public function isNextMonth() + { + return $this->month === $this->nowWithSameTz()->addMonthNoOverflow()->month; + } + + /** + * Determines if the instance is within the last month. + * + * @return bool + */ + public function isLastMonth() + { + return $this->month === $this->nowWithSameTz()->subMonthNoOverflow()->month; + } + + /** + * Determines if the instance is within next year. + * + * @return bool + */ + public function isNextYear() + { + return $this->year === $this->nowWithSameTz()->addYear()->year; + } + + /** + * Determines if the instance is within the previous year. + * + * @return bool + */ + public function isLastYear() + { + return $this->year === $this->nowWithSameTz()->subYear()->year; + } + + /** + * Determines if the instance is in the future, ie. greater (after) than now. + * + * @return bool + */ + public function isFuture() + { + return $this->gt($this->nowWithSameTz()); + } + + /** + * Determines if the instance is in the past, ie. less (before) than now. + * + * @return bool + */ + public function isPast() + { + return $this->lt($this->nowWithSameTz()); + } + + /** + * Determines if the instance is a leap year. + * + * @return bool + */ + public function isLeapYear() + { + return $this->format('L') === '1'; + } + + /** + * Determines if the instance is a long year + * + * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates + * + * @return bool + */ + public function isLongYear() + { + return static::create($this->year, 12, 28, 0, 0, 0, $this->tz)->weekOfYear === 53; + } + + /** + * Compares the formatted values of the two dates. + * + * @param string $format The date formats to compare. + * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day. + * + * @throws \InvalidArgumentException + * + * @return bool + */ + public function isSameAs($format, $date = null) + { + $date = $date ?: static::now($this->tz); + + static::expectDateTime($date, 'null'); + + return $this->format($format) === $date->format($format); + } + + /** + * Determines if the instance is in the current year. + * + * @return bool + */ + public function isCurrentYear() + { + return $this->isSameYear(); + } + + /** + * Checks if the passed in date is in the same year as the instance year. + * + * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day. + * + * @return bool + */ + public function isSameYear($date = null) + { + return $this->isSameAs('Y', $date); + } + + /** + * Determines if the instance is in the current month. + * + * @return bool + */ + public function isCurrentQuarter() + { + return $this->isSameQuarter(); + } + + /** + * Checks if the passed in date is in the same quarter as the instance quarter (and year if needed). + * + * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day. + * @param bool $ofSameYear Check if it is the same month in the same year. + * + * @return bool + */ + public function isSameQuarter($date = null, $ofSameYear = null) + { + $date = $date ? static::instance($date) : static::now($this->tz); + + static::expectDateTime($date, 'null'); + + $ofSameYear = is_null($ofSameYear) ? static::shouldCompareYearWithMonth() : $ofSameYear; + + return $this->quarter === $date->quarter && (!$ofSameYear || $this->isSameYear($date)); + } + + /** + * Determines if the instance is in the current month. + * + * @param bool $ofSameYear Check if it is the same month in the same year. + * + * @return bool + */ + public function isCurrentMonth($ofSameYear = null) + { + return $this->isSameMonth(null, $ofSameYear); + } + + /** + * Checks if the passed in date is in the same month as the instance´s month. + * + * Note that this defaults to only comparing the month while ignoring the year. + * To test if it is the same exact month of the same year, pass in true as the second parameter. + * + * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date. + * @param bool $ofSameYear Check if it is the same month in the same year. + * + * @return bool + */ + public function isSameMonth($date = null, $ofSameYear = null) + { + $ofSameYear = is_null($ofSameYear) ? static::shouldCompareYearWithMonth() : $ofSameYear; + + return $this->isSameAs($ofSameYear ? 'Y-m' : 'm', $date); + } + + /** + * Determines if the instance is in the current day. + * + * @return bool + */ + public function isCurrentDay() + { + return $this->isSameDay(); + } + + /** + * Checks if the passed in date is the same exact day as the instance´s day. + * + * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date. + * + * @return bool + */ + public function isSameDay($date = null) + { + return $this->isSameAs('Y-m-d', $date); + } + + /** + * Determines if the instance is in the current hour. + * + * @return bool + */ + public function isCurrentHour() + { + return $this->isSameHour(); + } + + /** + * Checks if the passed in date is the same exact hour as the instance´s hour. + * + * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date. + * + * @return bool + */ + public function isSameHour($date = null) + { + return $this->isSameAs('Y-m-d H', $date); + } + + /** + * Determines if the instance is in the current minute. + * + * @return bool + */ + public function isCurrentMinute() + { + return $this->isSameMinute(); + } + + /** + * Checks if the passed in date is the same exact minute as the instance´s minute. + * + * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date. + * + * @return bool + */ + public function isSameMinute($date = null) + { + return $this->isSameAs('Y-m-d H:i', $date); + } + + /** + * Determines if the instance is in the current second. + * + * @return bool + */ + public function isCurrentSecond() + { + return $this->isSameSecond(); + } + + /** + * Checks if the passed in date is the same exact second as the instance´s second. + * + * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date. + * + * @return bool + */ + public function isSameSecond($date = null) + { + return $this->isSameAs('Y-m-d H:i:s', $date); + } + + /** + * Checks if this day is a specific day of the week. + * + * @param int $dayOfWeek + * + * @return bool + */ + public function isDayOfWeek($dayOfWeek) + { + return $this->dayOfWeek === $dayOfWeek; + } + + /** + * Checks if this day is a Sunday. + * + * @return bool + */ + public function isSunday() + { + return $this->dayOfWeek === static::SUNDAY; + } + + /** + * Checks if this day is a Monday. + * + * @return bool + */ + public function isMonday() + { + return $this->dayOfWeek === static::MONDAY; + } + + /** + * Checks if this day is a Tuesday. + * + * @return bool + */ + public function isTuesday() + { + return $this->dayOfWeek === static::TUESDAY; + } + + /** + * Checks if this day is a Wednesday. + * + * @return bool + */ + public function isWednesday() + { + return $this->dayOfWeek === static::WEDNESDAY; + } + + /** + * Checks if this day is a Thursday. + * + * @return bool + */ + public function isThursday() + { + return $this->dayOfWeek === static::THURSDAY; + } + + /** + * Checks if this day is a Friday. + * + * @return bool + */ + public function isFriday() + { + return $this->dayOfWeek === static::FRIDAY; + } + + /** + * Checks if this day is a Saturday. + * + * @return bool + */ + public function isSaturday() + { + return $this->dayOfWeek === static::SATURDAY; + } + + /** + * Check if its the birthday. Compares the date/month values of the two dates. + * + * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day. + * + * @return bool + */ + public function isBirthday($date = null) + { + return $this->isSameAs('md', $date); + } + + /** + * Check if today is the last day of the Month + * + * @return bool + */ + public function isLastOfMonth() + { + return $this->day === $this->daysInMonth; + } + + /** + * Check if the instance is start of day / midnight. + * + * @param bool $checkMicroseconds check time at microseconds precision + * /!\ Warning, this is not reliable with PHP < 7.1.4 + * + * @return bool + */ + public function isStartOfDay($checkMicroseconds = false) + { + return $checkMicroseconds + ? $this->format('H:i:s.u') === '00:00:00.000000' + : $this->format('H:i:s') === '00:00:00'; + } + + /** + * Check if the instance is end of day. + * + * @param bool $checkMicroseconds check time at microseconds precision + * /!\ Warning, this is not reliable with PHP < 7.1.4 + * + * @return bool + */ + public function isEndOfDay($checkMicroseconds = false) + { + return $checkMicroseconds + ? $this->format('H:i:s.u') === '23:59:59.999999' + : $this->format('H:i:s') === '23:59:59'; + } + + /** + * Check if the instance is start of day / midnight. + * + * @return bool + */ + public function isMidnight() + { + return $this->isStartOfDay(); + } + + /** + * Check if the instance is midday. + * + * @return bool + */ + public function isMidday() + { + return $this->format('G:i:s') === static::$midDayAt.':00:00'; + } + + /** + * Checks if the (date)time string is in a given format. + * + * @param string $date + * @param string $format + * + * @return bool + */ + public static function hasFormat($date, $format) + { + try { + // Try to create a DateTime object. Throws an InvalidArgumentException if the provided time string + // doesn't match the format in any way. + static::createFromFormat($format, $date); + + // createFromFormat() is known to handle edge cases silently. + // E.g. "1975-5-1" (Y-n-j) will still be parsed correctly when "Y-m-d" is supplied as the format. + // To ensure we're really testing against our desired format, perform an additional regex validation. + $regex = strtr( + preg_quote($format, '/'), + static::$regexFormats + ); + + return (bool) preg_match('/^'.$regex.'$/', $date); + } catch (InvalidArgumentException $e) { + } + + return false; + } + + /////////////////////////////////////////////////////////////////// + /////////////////// ADDITIONS AND SUBTRACTIONS //////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Add centuries to the instance. Positive $value travels forward while + * negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addCenturies($value) + { + return $this->addYears(static::YEARS_PER_CENTURY * $value); + } + + /** + * Add a century to the instance + * + * @param int $value + * + * @return static + */ + public function addCentury($value = 1) + { + return $this->addCenturies($value); + } + + /** + * Remove centuries from the instance + * + * @param int $value + * + * @return static + */ + public function subCenturies($value) + { + return $this->addCenturies(-1 * $value); + } + + /** + * Remove a century from the instance + * + * @param int $value + * + * @return static + */ + public function subCentury($value = 1) + { + return $this->subCenturies($value); + } + + /** + * Add years to the instance. Positive $value travel forward while + * negative $value travel into the past. + * + * @param int $value + * + * @return static + */ + public function addYears($value) + { + if ($this->shouldOverflowYears()) { + return $this->addYearsWithOverflow($value); + } + + return $this->addYearsNoOverflow($value); + } + + /** + * Add a year to the instance + * + * @param int $value + * + * @return static + */ + public function addYear($value = 1) + { + return $this->addYears($value); + } + + /** + * Add years to the instance with no overflow of months + * Positive $value travel forward while + * negative $value travel into the past. + * + * @param int $value + * + * @return static + */ + public function addYearsNoOverflow($value) + { + return $this->addMonthsNoOverflow($value * static::MONTHS_PER_YEAR); + } + + /** + * Add year with overflow months set to false + * + * @param int $value + * + * @return static + */ + public function addYearNoOverflow($value = 1) + { + return $this->addYearsNoOverflow($value); + } + + /** + * Add years to the instance. + * Positive $value travel forward while + * negative $value travel into the past. + * + * @param int $value + * + * @return static + */ + public function addYearsWithOverflow($value) + { + return $this->modify((int) $value.' year'); + } + + /** + * Add year with overflow. + * + * @param int $value + * + * @return static + */ + public function addYearWithOverflow($value = 1) + { + return $this->addYearsWithOverflow($value); + } + + /** + * Remove years from the instance. + * + * @param int $value + * + * @return static + */ + public function subYears($value) + { + return $this->addYears(-1 * $value); + } + + /** + * Remove a year from the instance + * + * @param int $value + * + * @return static + */ + public function subYear($value = 1) + { + return $this->subYears($value); + } + + /** + * Remove years from the instance with no month overflow. + * + * @param int $value + * + * @return static + */ + public function subYearsNoOverflow($value) + { + return $this->subMonthsNoOverflow($value * static::MONTHS_PER_YEAR); + } + + /** + * Remove year from the instance with no month overflow + * + * @param int $value + * + * @return static + */ + public function subYearNoOverflow($value = 1) + { + return $this->subYearsNoOverflow($value); + } + + /** + * Remove years from the instance. + * + * @param int $value + * + * @return static + */ + public function subYearsWithOverflow($value) + { + return $this->subMonthsWithOverflow($value * static::MONTHS_PER_YEAR); + } + + /** + * Remove year from the instance. + * + * @param int $value + * + * @return static + */ + public function subYearWithOverflow($value = 1) + { + return $this->subYearsWithOverflow($value); + } + + /** + * Add quarters to the instance. Positive $value travels forward while + * negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addQuarters($value) + { + return $this->addMonths(static::MONTHS_PER_QUARTER * $value); + } + + /** + * Add a quarter to the instance + * + * @param int $value + * + * @return static + */ + public function addQuarter($value = 1) + { + return $this->addQuarters($value); + } + + /** + * Remove quarters from the instance + * + * @param int $value + * + * @return static + */ + public function subQuarters($value) + { + return $this->addQuarters(-1 * $value); + } + + /** + * Remove a quarter from the instance + * + * @param int $value + * + * @return static + */ + public function subQuarter($value = 1) + { + return $this->subQuarters($value); + } + + /** + * Add months to the instance. Positive $value travels forward while + * negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addMonths($value) + { + if (static::shouldOverflowMonths()) { + return $this->addMonthsWithOverflow($value); + } + + return $this->addMonthsNoOverflow($value); + } + + /** + * Add a month to the instance + * + * @param int $value + * + * @return static + */ + public function addMonth($value = 1) + { + return $this->addMonths($value); + } + + /** + * Remove months from the instance + * + * @param int $value + * + * @return static + */ + public function subMonths($value) + { + return $this->addMonths(-1 * $value); + } + + /** + * Remove a month from the instance + * + * @param int $value + * + * @return static + */ + public function subMonth($value = 1) + { + return $this->subMonths($value); + } + + /** + * Add months to the instance. Positive $value travels forward while + * negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addMonthsWithOverflow($value) + { + return $this->modify((int) $value.' month'); + } + + /** + * Add a month to the instance + * + * @param int $value + * + * @return static + */ + public function addMonthWithOverflow($value = 1) + { + return $this->addMonthsWithOverflow($value); + } + + /** + * Remove months from the instance + * + * @param int $value + * + * @return static + */ + public function subMonthsWithOverflow($value) + { + return $this->addMonthsWithOverflow(-1 * $value); + } + + /** + * Remove a month from the instance + * + * @param int $value + * + * @return static + */ + public function subMonthWithOverflow($value = 1) + { + return $this->subMonthsWithOverflow($value); + } + + /** + * Add months without overflowing to the instance. Positive $value + * travels forward while negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addMonthsNoOverflow($value) + { + $day = $this->day; + + $this->modify((int) $value.' month'); + + if ($day !== $this->day) { + $this->modify('last day of previous month'); + } + + return $this; + } + + /** + * Add a month with no overflow to the instance + * + * @param int $value + * + * @return static + */ + public function addMonthNoOverflow($value = 1) + { + return $this->addMonthsNoOverflow($value); + } + + /** + * Remove months with no overflow from the instance + * + * @param int $value + * + * @return static + */ + public function subMonthsNoOverflow($value) + { + return $this->addMonthsNoOverflow(-1 * $value); + } + + /** + * Remove a month with no overflow from the instance + * + * @param int $value + * + * @return static + */ + public function subMonthNoOverflow($value = 1) + { + return $this->subMonthsNoOverflow($value); + } + + /** + * Add days to the instance. Positive $value travels forward while + * negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addDays($value) + { + return $this->modify((int) $value.' day'); + } + + /** + * Add a day to the instance + * + * @param int $value + * + * @return static + */ + public function addDay($value = 1) + { + return $this->addDays($value); + } + + /** + * Remove days from the instance + * + * @param int $value + * + * @return static + */ + public function subDays($value) + { + return $this->addDays(-1 * $value); + } + + /** + * Remove a day from the instance + * + * @param int $value + * + * @return static + */ + public function subDay($value = 1) + { + return $this->subDays($value); + } + + /** + * Add weekdays to the instance. Positive $value travels forward while + * negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addWeekdays($value) + { + // Fix for weekday bug https://bugs.php.net/bug.php?id=54909 + $t = $this->toTimeString(); + $this->modify((int) $value.' weekday'); + + return $this->setTimeFromTimeString($t); + } + + /** + * Add a weekday to the instance + * + * @param int $value + * + * @return static + */ + public function addWeekday($value = 1) + { + return $this->addWeekdays($value); + } + + /** + * Remove weekdays from the instance + * + * @param int $value + * + * @return static + */ + public function subWeekdays($value) + { + return $this->addWeekdays(-1 * $value); + } + + /** + * Remove a weekday from the instance + * + * @param int $value + * + * @return static + */ + public function subWeekday($value = 1) + { + return $this->subWeekdays($value); + } + + /** + * Add weeks to the instance. Positive $value travels forward while + * negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addWeeks($value) + { + return $this->modify((int) $value.' week'); + } + + /** + * Add a week to the instance + * + * @param int $value + * + * @return static + */ + public function addWeek($value = 1) + { + return $this->addWeeks($value); + } + + /** + * Remove weeks to the instance + * + * @param int $value + * + * @return static + */ + public function subWeeks($value) + { + return $this->addWeeks(-1 * $value); + } + + /** + * Remove a week from the instance + * + * @param int $value + * + * @return static + */ + public function subWeek($value = 1) + { + return $this->subWeeks($value); + } + + /** + * Add hours to the instance. Positive $value travels forward while + * negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addHours($value) + { + return $this->modify((int) $value.' hour'); + } + + /** + * Add hours to the instance using timestamp. Positive $value travels + * forward while negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addRealHours($value) + { + return $this->addRealMinutes($value * static::MINUTES_PER_HOUR); + } + + /** + * Add an hour to the instance. + * + * @param int $value + * + * @return static + */ + public function addHour($value = 1) + { + return $this->addHours($value); + } + + /** + * Add an hour to the instance using timestamp. + * + * @param int $value + * + * @return static + */ + public function addRealHour($value = 1) + { + return $this->addRealHours($value); + } + + /** + * Remove hours from the instance. + * + * @param int $value + * + * @return static + */ + public function subHours($value) + { + return $this->addHours(-1 * $value); + } + + /** + * Remove hours from the instance using timestamp. + * + * @param int $value + * + * @return static + */ + public function subRealHours($value) + { + return $this->addRealHours(-1 * $value); + } + + /** + * Remove an hour from the instance. + * + * @param int $value + * + * @return static + */ + public function subHour($value = 1) + { + return $this->subHours($value); + } + + /** + * Remove an hour from the instance. + * + * @param int $value + * + * @return static + */ + public function subRealHour($value = 1) + { + return $this->subRealHours($value); + } + + /** + * Add minutes to the instance using timestamp. Positive $value + * travels forward while negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addMinutes($value) + { + return $this->modify((int) $value.' minute'); + } + + /** + * Add minutes to the instance using timestamp. Positive $value travels + * forward while negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addRealMinutes($value) + { + return $this->addRealSeconds($value * static::SECONDS_PER_MINUTE); + } + + /** + * Add a minute to the instance. + * + * @param int $value + * + * @return static + */ + public function addMinute($value = 1) + { + return $this->addMinutes($value); + } + + /** + * Add a minute to the instance using timestamp. + * + * @param int $value + * + * @return static + */ + public function addRealMinute($value = 1) + { + return $this->addRealMinutes($value); + } + + /** + * Remove a minute from the instance. + * + * @param int $value + * + * @return static + */ + public function subMinute($value = 1) + { + return $this->subMinutes($value); + } + + /** + * Remove a minute from the instance using timestamp. + * + * @param int $value + * + * @return static + */ + public function subRealMinute($value = 1) + { + return $this->addRealMinutes(-1 * $value); + } + + /** + * Remove minutes from the instance. + * + * @param int $value + * + * @return static + */ + public function subMinutes($value) + { + return $this->addMinutes(-1 * $value); + } + + /** + * Remove a minute from the instance using timestamp. + * + * @param int $value + * + * @return static + */ + public function subRealMinutes($value = 1) + { + return $this->subRealMinute($value); + } + + /** + * Add seconds to the instance. Positive $value travels forward while + * negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addSeconds($value) + { + return $this->modify((int) $value.' second'); + } + + /** + * Add seconds to the instance using timestamp. Positive $value travels + * forward while negative $value travels into the past. + * + * @param int $value + * + * @return static + */ + public function addRealSeconds($value) + { + return $this->setTimestamp($this->getTimestamp() + $value); + } + + /** + * Add a second to the instance. + * + * @param int $value + * + * @return static + */ + public function addSecond($value = 1) + { + return $this->addSeconds($value); + } + + /** + * Add a second to the instance using timestamp. + * + * @param int $value + * + * @return static + */ + public function addRealSecond($value = 1) + { + return $this->addRealSeconds($value); + } + + /** + * Remove seconds from the instance. + * + * @param int $value + * + * @return static + */ + public function subSeconds($value) + { + return $this->addSeconds(-1 * $value); + } + + /** + * Remove seconds from the instance using timestamp. + * + * @param int $value + * + * @return static + */ + public function subRealSeconds($value) + { + return $this->addRealSeconds(-1 * $value); + } + + /** + * Remove a second from the instance + * + * @param int $value + * + * @return static + */ + public function subSecond($value = 1) + { + return $this->subSeconds($value); + } + + /** + * Remove a second from the instance using timestamp. + * + * @param int $value + * + * @return static + */ + public function subRealSecond($value = 1) + { + return $this->subRealSeconds($value); + } + + /////////////////////////////////////////////////////////////////// + /////////////////////////// DIFFERENCES /////////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * @param DateInterval $diff + * @param bool $absolute + * @param bool $trimMicroseconds + * + * @return CarbonInterval + */ + protected static function fixDiffInterval(DateInterval $diff, $absolute, $trimMicroseconds) + { + $diff = CarbonInterval::instance($diff, $trimMicroseconds); + + // @codeCoverageIgnoreStart + if (version_compare(PHP_VERSION, '7.1.0-dev', '<')) { + return $diff; + } + + // Work-around for https://bugs.php.net/bug.php?id=77145 + if ($diff->f > 0 && $diff->y === -1 && $diff->m === 11 && $diff->d >= 27 && $diff->h === 23 && $diff->i === 59 && $diff->s === 59) { + $diff->y = 0; + $diff->m = 0; + $diff->d = 0; + $diff->h = 0; + $diff->i = 0; + $diff->s = 0; + $diff->f = (1000000 - round($diff->f * 1000000)) / 1000000; + $diff->invert(); + } elseif ($diff->f < 0) { + if ($diff->s !== 0 || $diff->i !== 0 || $diff->h !== 0 || $diff->d !== 0 || $diff->m !== 0 || $diff->y !== 0) { + $diff->f = (round($diff->f * 1000000) + 1000000) / 1000000; + $diff->s--; + if ($diff->s < 0) { + $diff->s += 60; + $diff->i--; + if ($diff->i < 0) { + $diff->i += 60; + $diff->h--; + if ($diff->h < 0) { + $diff->h += 24; + $diff->d--; + if ($diff->d < 0) { + $diff->d += 30; + $diff->m--; + if ($diff->m < 0) { + $diff->m += 12; + $diff->y--; + } + } + } + } + } + } else { + $diff->f *= -1; + $diff->invert(); + } + } + // @codeCoverageIgnoreEnd + if ($absolute && $diff->invert) { + $diff->invert(); + } + + return $diff; + } + + /** + * Get the difference as a CarbonInterval instance. + * + * Pass false as second argument to get a microseconds-precise interval. Else + * microseconds in the original interval will not be kept. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * @param bool $trimMicroseconds (true by default) + * + * @return CarbonInterval + */ + public function diffAsCarbonInterval($date = null, $absolute = true, $trimMicroseconds = true) + { + $from = $this; + $to = $this->resolveCarbon($date); + + if ($trimMicroseconds) { + $from = $from->copy()->startOfSecond(); + $to = $to->copy()->startOfSecond(); + } + + return static::fixDiffInterval($from->diff($to, $absolute), $absolute, $trimMicroseconds); + } + + /** + * Get the difference in years + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInYears($date = null, $absolute = true) + { + return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%y'); + } + + /** + * Get the difference in months + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInMonths($date = null, $absolute = true) + { + $date = $this->resolveCarbon($date); + + return $this->diffInYears($date, $absolute) * static::MONTHS_PER_YEAR + (int) $this->diff($date, $absolute)->format('%r%m'); + } + + /** + * Get the difference in weeks + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInWeeks($date = null, $absolute = true) + { + return (int) ($this->diffInDays($date, $absolute) / static::DAYS_PER_WEEK); + } + + /** + * Get the difference in days + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInDays($date = null, $absolute = true) + { + return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%a'); + } + + /** + * Get the difference in days using a filter closure + * + * @param Closure $callback + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInDaysFiltered(Closure $callback, $date = null, $absolute = true) + { + return $this->diffFiltered(CarbonInterval::day(), $callback, $date, $absolute); + } + + /** + * Get the difference in hours using a filter closure + * + * @param Closure $callback + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInHoursFiltered(Closure $callback, $date = null, $absolute = true) + { + return $this->diffFiltered(CarbonInterval::hour(), $callback, $date, $absolute); + } + + /** + * Get the difference by the given interval using a filter closure + * + * @param CarbonInterval $ci An interval to traverse by + * @param Closure $callback + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffFiltered(CarbonInterval $ci, Closure $callback, $date = null, $absolute = true) + { + $start = $this; + $end = $this->resolveCarbon($date); + $inverse = false; + + if ($end < $start) { + $start = $end; + $end = $this; + $inverse = true; + } + + $period = new DatePeriod($start, $ci, $end); + $values = array_filter(iterator_to_array($period), function ($date) use ($callback) { + return call_user_func($callback, Carbon::instance($date)); + }); + + $diff = count($values); + + return $inverse && !$absolute ? -$diff : $diff; + } + + /** + * Get the difference in weekdays + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInWeekdays($date = null, $absolute = true) + { + return $this->diffInDaysFiltered(function (Carbon $date) { + return $date->isWeekday(); + }, $date, $absolute); + } + + /** + * Get the difference in weekend days using a filter + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInWeekendDays($date = null, $absolute = true) + { + return $this->diffInDaysFiltered(function (Carbon $date) { + return $date->isWeekend(); + }, $date, $absolute); + } + + /** + * Get the difference in hours. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInHours($date = null, $absolute = true) + { + return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR); + } + + /** + * Get the difference in hours using timestamps. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInRealHours($date = null, $absolute = true) + { + return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR); + } + + /** + * Get the difference in minutes. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInMinutes($date = null, $absolute = true) + { + return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE); + } + + /** + * Get the difference in minutes using timestamps. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInRealMinutes($date = null, $absolute = true) + { + return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE); + } + + /** + * Get the difference in seconds. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInSeconds($date = null, $absolute = true) + { + $diff = $this->diff($this->resolveCarbon($date)); + if (!$diff->days && version_compare(PHP_VERSION, '5.4.0-dev', '>=')) { + $diff = static::fixDiffInterval($diff, $absolute, false); + } + $value = $diff->days * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE + + $diff->h * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE + + $diff->i * static::SECONDS_PER_MINUTE + + $diff->s; + + return $absolute || !$diff->invert ? $value : -$value; + } + + /** + * Get the difference in seconds using timestamps. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInRealSeconds($date = null, $absolute = true) + { + $date = $this->resolveCarbon($date); + $value = $date->getTimestamp() - $this->getTimestamp(); + + return $absolute ? abs($value) : $value; + } + + /** + * Get the difference in milliseconds. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInMilliseconds($date = null, $absolute = true) + { + return (int) ($this->diffInMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND); + } + + /** + * Get the difference in milliseconds using timestamps. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInRealMilliseconds($date = null, $absolute = true) + { + return (int) ($this->diffInRealMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND); + } + + /** + * Get the difference in microseconds. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInMicroseconds($date = null, $absolute = true) + { + $diff = $this->diff($this->resolveCarbon($date)); + $micro = isset($diff->f) ? $diff->f : 0; + $value = (int) round((((($diff->days * static::HOURS_PER_DAY) + + $diff->h) * static::MINUTES_PER_HOUR + + $diff->i) * static::SECONDS_PER_MINUTE + + ($micro + $diff->s)) * static::MICROSECONDS_PER_SECOND); + + return $absolute || !$diff->invert ? $value : -$value; + } + + /** + * Get the difference in microseconds using timestamps. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * @param bool $absolute Get the absolute of the difference + * + * @return int + */ + public function diffInRealMicroseconds($date = null, $absolute = true) + { + /** @var Carbon $date */ + $date = $this->resolveCarbon($date); + $value = ($date->timestamp - $this->timestamp) * static::MICROSECONDS_PER_SECOND + + $date->micro - $this->micro; + + return $absolute ? abs($value) : $value; + } + + /** + * The number of seconds since midnight. + * + * @return int + */ + public function secondsSinceMidnight() + { + return $this->diffInSeconds($this->copy()->startOfDay()); + } + + /** + * The number of seconds until 23:59:59. + * + * @return int + */ + public function secondsUntilEndOfDay() + { + return $this->diffInSeconds($this->copy()->endOfDay()); + } + + /** + * Get the difference in a human readable format in the current locale. + * + * When comparing a value in the past to default now: + * 1 hour ago + * 5 months ago + * + * When comparing a value in the future to default now: + * 1 hour from now + * 5 months from now + * + * When comparing a value in the past to another value: + * 1 hour before + * 5 months before + * + * When comparing a value in the future to another value: + * 1 hour after + * 5 months after + * + * @param Carbon|null $other + * @param bool $absolute removes time difference modifiers ago, after, etc + * @param bool $short displays short format of time units + * @param int $parts displays number of parts in the interval + * + * @return string + */ + public function diffForHumans($other = null, $absolute = false, $short = false, $parts = 1) + { + $isNow = $other === null; + $relativeToNow = $isNow; + + if ($absolute === static::DIFF_RELATIVE_TO_NOW) { + $absolute = false; + $relativeToNow = true; + } elseif ($absolute === static::DIFF_RELATIVE_TO_OTHER) { + $absolute = false; + $relativeToNow = false; + } + + $interval = array(); + + $parts = min(6, max(1, (int) $parts)); + $count = 1; + $unit = $short ? 's' : 'second'; + + if ($isNow) { + $other = $this->nowWithSameTz(); + } elseif (!$other instanceof DateTime && !$other instanceof DateTimeInterface) { + $other = static::parse($other); + } + + $diffInterval = $this->diff($other); + + $diffIntervalArray = array( + array('value' => $diffInterval->y, 'unit' => 'year', 'unitShort' => 'y'), + array('value' => $diffInterval->m, 'unit' => 'month', 'unitShort' => 'm'), + array('value' => $diffInterval->d, 'unit' => 'day', 'unitShort' => 'd'), + array('value' => $diffInterval->h, 'unit' => 'hour', 'unitShort' => 'h'), + array('value' => $diffInterval->i, 'unit' => 'minute', 'unitShort' => 'min'), + array('value' => $diffInterval->s, 'unit' => 'second', 'unitShort' => 's'), + ); + + foreach ($diffIntervalArray as $diffIntervalData) { + if ($diffIntervalData['value'] > 0) { + $unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit']; + $count = $diffIntervalData['value']; + + if ($diffIntervalData['unit'] === 'day' && $count >= static::DAYS_PER_WEEK) { + $unit = $short ? 'w' : 'week'; + $count = (int) ($count / static::DAYS_PER_WEEK); + + $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count)); + + // get the count days excluding weeks (might be zero) + $numOfDaysCount = (int) ($diffIntervalData['value'] - ($count * static::DAYS_PER_WEEK)); + + if ($numOfDaysCount > 0 && count($interval) < $parts) { + $unit = $short ? 'd' : 'day'; + $count = $numOfDaysCount; + $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count)); + } + } else { + $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count)); + } + } + + // break the loop after we get the required number of parts in array + if (count($interval) >= $parts) { + break; + } + } + + if (count($interval) === 0) { + if ($isNow && static::getHumanDiffOptions() & self::JUST_NOW) { + $key = 'diff_now'; + $translation = static::translator()->trans($key); + if ($translation !== $key) { + return $translation; + } + } + $count = static::getHumanDiffOptions() & self::NO_ZERO_DIFF ? 1 : 0; + $unit = $short ? 's' : 'second'; + $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count)); + } + + // join the interval parts by a space + $time = implode(' ', $interval); + + unset($diffIntervalArray, $interval); + + if ($absolute) { + return $time; + } + + $isFuture = $diffInterval->invert === 1; + + $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before'); + + if ($parts === 1) { + if ($isNow && $unit === 'day') { + if ($count === 1 && static::getHumanDiffOptions() & self::ONE_DAY_WORDS) { + $key = $isFuture ? 'diff_tomorrow' : 'diff_yesterday'; + $translation = static::translator()->trans($key); + if ($translation !== $key) { + return $translation; + } + } + if ($count === 2 && static::getHumanDiffOptions() & self::TWO_DAY_WORDS) { + $key = $isFuture ? 'diff_after_tomorrow' : 'diff_before_yesterday'; + $translation = static::translator()->trans($key); + if ($translation !== $key) { + return $translation; + } + } + } + // Some languages have special pluralization for past and future tense. + $key = $unit.'_'.$transId; + if ($key !== static::translator()->transChoice($key, $count)) { + $time = static::translator()->transChoice($key, $count, array(':count' => $count)); + } + } + + return static::translator()->trans($transId, array(':time' => $time)); + } + + /** + * @alias diffForHumans + * + * Get the difference in a human readable format in the current locale. + * + * When comparing a value in the past to default now: + * 1 hour ago + * 5 months ago + * + * When comparing a value in the future to default now: + * 1 hour from now + * 5 months from now + * + * When comparing a value in the past to another value: + * 1 hour before + * 5 months before + * + * When comparing a value in the future to another value: + * 1 hour after + * 5 months after + * + * @param Carbon|null $other + * @param bool $absolute removes time difference modifiers ago, after, etc + * @param bool $short displays short format of time units + * @param int $parts displays number of parts in the interval + * + * @return string + */ + public function from($other = null, $absolute = false, $short = false, $parts = 1) + { + if (!$other && !$absolute) { + $absolute = static::DIFF_RELATIVE_TO_NOW; + } + + return $this->diffForHumans($other, $absolute, $short, $parts); + } + + /** + * @alias diffForHumans + * + * Get the difference in a human readable format in the current locale. + * + * When comparing a value in the past to default now: + * 1 hour ago + * 5 months ago + * + * When comparing a value in the future to default now: + * 1 hour from now + * 5 months from now + * + * When comparing a value in the past to another value: + * 1 hour before + * 5 months before + * + * When comparing a value in the future to another value: + * 1 hour after + * 5 months after + * + * @param Carbon|null $other + * @param bool $absolute removes time difference modifiers ago, after, etc + * @param bool $short displays short format of time units + * @param int $parts displays number of parts in the interval + * + * @return string + */ + public function since($other = null, $absolute = false, $short = false, $parts = 1) + { + return $this->diffForHumans($other, $absolute, $short, $parts); + } + + /** + * Get the difference in a human readable format in the current locale from an other + * instance given (or now if null given) to current instance. + * + * When comparing a value in the past to default now: + * 1 hour from now + * 5 months from now + * + * When comparing a value in the future to default now: + * 1 hour ago + * 5 months ago + * + * When comparing a value in the past to another value: + * 1 hour after + * 5 months after + * + * When comparing a value in the future to another value: + * 1 hour before + * 5 months before + * + * @param Carbon|null $other + * @param bool $absolute removes time difference modifiers ago, after, etc + * @param bool $short displays short format of time units + * @param int $parts displays number of parts in the interval + * + * @return string + */ + public function to($other = null, $absolute = false, $short = false, $parts = 1) + { + if (!$other && !$absolute) { + $absolute = static::DIFF_RELATIVE_TO_NOW; + } + + return $this->resolveCarbon($other)->diffForHumans($this, $absolute, $short, $parts); + } + + /** + * @alias to + * + * Get the difference in a human readable format in the current locale from an other + * instance given (or now if null given) to current instance. + * + * @param Carbon|null $other + * @param bool $absolute removes time difference modifiers ago, after, etc + * @param bool $short displays short format of time units + * @param int $parts displays number of parts in the interval + * + * @return string + */ + public function until($other = null, $absolute = false, $short = false, $parts = 1) + { + return $this->to($other, $absolute, $short, $parts); + } + + /** + * Get the difference in a human readable format in the current locale from current + * instance to now. + * + * @param bool $absolute removes time difference modifiers ago, after, etc + * @param bool $short displays short format of time units + * @param int $parts displays number of parts in the interval + * + * @return string + */ + public function fromNow($absolute = null, $short = false, $parts = 1) + { + $other = null; + + if ($absolute instanceof DateTimeInterface) { + list($other, $absolute, $short, $parts) = array_pad(func_get_args(), 5, null); + } + + return $this->from($other, $absolute, $short, $parts); + } + + /** + * Get the difference in a human readable format in the current locale from an other + * instance given to now + * + * @param bool $absolute removes time difference modifiers ago, after, etc + * @param bool $short displays short format of time units + * @param int $parts displays number of parts in the interval + * + * @return string + */ + public function toNow($absolute = null, $short = false, $parts = 1) + { + return $this->to(null, $absolute, $short, $parts); + } + + /** + * Get the difference in a human readable format in the current locale from an other + * instance given to now + * + * @param bool $absolute removes time difference modifiers ago, after, etc + * @param bool $short displays short format of time units + * @param int $parts displays number of parts in the interval + * + * @return string + */ + public function ago($absolute = null, $short = false, $parts = 1) + { + $other = null; + + if ($absolute instanceof DateTimeInterface) { + list($other, $absolute, $short, $parts) = array_pad(func_get_args(), 5, null); + } + + return $this->from($other, $absolute, $short, $parts); + } + + /////////////////////////////////////////////////////////////////// + //////////////////////////// MODIFIERS //////////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Resets the time to 00:00:00 start of day + * + * @return static + */ + public function startOfDay() + { + return $this->modify('00:00:00.000000'); + } + + /** + * Resets the time to 23:59:59 end of day + * + * @return static + */ + public function endOfDay() + { + return $this->modify('23:59:59.999999'); + } + + /** + * Resets the date to the first day of the month and the time to 00:00:00 + * + * @return static + */ + public function startOfMonth() + { + return $this->setDate($this->year, $this->month, 1)->startOfDay(); + } + + /** + * Resets the date to end of the month and time to 23:59:59 + * + * @return static + */ + public function endOfMonth() + { + return $this->setDate($this->year, $this->month, $this->daysInMonth)->endOfDay(); + } + + /** + * Resets the date to the first day of the quarter and the time to 00:00:00 + * + * @return static + */ + public function startOfQuarter() + { + $month = ($this->quarter - 1) * static::MONTHS_PER_QUARTER + 1; + + return $this->setDate($this->year, $month, 1)->startOfDay(); + } + + /** + * Resets the date to end of the quarter and time to 23:59:59 + * + * @return static + */ + public function endOfQuarter() + { + return $this->startOfQuarter()->addMonths(static::MONTHS_PER_QUARTER - 1)->endOfMonth(); + } + + /** + * Resets the date to the first day of the year and the time to 00:00:00 + * + * @return static + */ + public function startOfYear() + { + return $this->setDate($this->year, 1, 1)->startOfDay(); + } + + /** + * Resets the date to end of the year and time to 23:59:59 + * + * @return static + */ + public function endOfYear() + { + return $this->setDate($this->year, 12, 31)->endOfDay(); + } + + /** + * Resets the date to the first day of the decade and the time to 00:00:00 + * + * @return static + */ + public function startOfDecade() + { + $year = $this->year - $this->year % static::YEARS_PER_DECADE; + + return $this->setDate($year, 1, 1)->startOfDay(); + } + + /** + * Resets the date to end of the decade and time to 23:59:59 + * + * @return static + */ + public function endOfDecade() + { + $year = $this->year - $this->year % static::YEARS_PER_DECADE + static::YEARS_PER_DECADE - 1; + + return $this->setDate($year, 12, 31)->endOfDay(); + } + + /** + * Resets the date to the first day of the century and the time to 00:00:00 + * + * @return static + */ + public function startOfCentury() + { + $year = $this->year - ($this->year - 1) % static::YEARS_PER_CENTURY; + + return $this->setDate($year, 1, 1)->startOfDay(); + } + + /** + * Resets the date to end of the century and time to 23:59:59 + * + * @return static + */ + public function endOfCentury() + { + $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_CENTURY + static::YEARS_PER_CENTURY; + + return $this->setDate($year, 12, 31)->endOfDay(); + } + + /** + * Resets the date to the first day of the century and the time to 00:00:00 + * + * @return static + */ + public function startOfMillennium() + { + $year = $this->year - ($this->year - 1) % static::YEARS_PER_MILLENNIUM; + + return $this->setDate($year, 1, 1)->startOfDay(); + } + + /** + * Resets the date to end of the century and time to 23:59:59 + * + * @return static + */ + public function endOfMillennium() + { + $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_MILLENNIUM + static::YEARS_PER_MILLENNIUM; + + return $this->setDate($year, 12, 31)->endOfDay(); + } + + /** + * Resets the date to the first day of week (defined in $weekStartsAt) and the time to 00:00:00 + * + * @return static + */ + public function startOfWeek() + { + while ($this->dayOfWeek !== static::$weekStartsAt) { + $this->subDay(); + } + + return $this->startOfDay(); + } + + /** + * Resets the date to end of week (defined in $weekEndsAt) and time to 23:59:59 + * + * @return static + */ + public function endOfWeek() + { + while ($this->dayOfWeek !== static::$weekEndsAt) { + $this->addDay(); + } + + return $this->endOfDay(); + } + + /** + * Modify to start of current hour, minutes and seconds become 0 + * + * @return static + */ + public function startOfHour() + { + return $this->setTime($this->hour, 0, 0); + } + + /** + * Modify to end of current hour, minutes and seconds become 59 + * + * @return static + */ + public function endOfHour() + { + return $this->modify("$this->hour:59:59.999999"); + } + + /** + * Modify to start of current minute, seconds become 0 + * + * @return static + */ + public function startOfMinute() + { + return $this->setTime($this->hour, $this->minute, 0); + } + + /** + * Modify to end of current minute, seconds become 59 + * + * @return static + */ + public function endOfMinute() + { + return $this->modify("$this->hour:$this->minute:59.999999"); + } + + /** + * Modify to start of current minute, seconds become 0 + * + * @return static + */ + public function startOfSecond() + { + return $this->modify("$this->hour:$this->minute:$this->second.0"); + } + + /** + * Modify to end of current minute, seconds become 59 + * + * @return static + */ + public function endOfSecond() + { + return $this->modify("$this->hour:$this->minute:$this->second.999999"); + } + + /** + * Modify to midday, default to self::$midDayAt + * + * @return static + */ + public function midDay() + { + return $this->setTime(self::$midDayAt, 0, 0); + } + + /** + * Modify to the next occurrence of a given day of the week. + * If no dayOfWeek is provided, modify to the next occurrence + * of the current day of the week. Use the supplied constants + * to indicate the desired dayOfWeek, ex. static::MONDAY. + * + * @param int|null $dayOfWeek + * + * @return static + */ + public function next($dayOfWeek = null) + { + if ($dayOfWeek === null) { + $dayOfWeek = $this->dayOfWeek; + } + + return $this->startOfDay()->modify('next '.static::$days[$dayOfWeek]); + } + + /** + * Go forward or backward to the next week- or weekend-day. + * + * @param bool $weekday + * @param bool $forward + * + * @return $this + */ + private function nextOrPreviousDay($weekday = true, $forward = true) + { + $step = $forward ? 1 : -1; + + do { + $this->addDay($step); + } while ($weekday ? $this->isWeekend() : $this->isWeekday()); + + return $this; + } + + /** + * Go forward to the next weekday. + * + * @return $this + */ + public function nextWeekday() + { + return $this->nextOrPreviousDay(); + } + + /** + * Go backward to the previous weekday. + * + * @return $this + */ + public function previousWeekday() + { + return $this->nextOrPreviousDay(true, false); + } + + /** + * Go forward to the next weekend day. + * + * @return $this + */ + public function nextWeekendDay() + { + return $this->nextOrPreviousDay(false); + } + + /** + * Go backward to the previous weekend day. + * + * @return $this + */ + public function previousWeekendDay() + { + return $this->nextOrPreviousDay(false, false); + } + + /** + * Modify to the previous occurrence of a given day of the week. + * If no dayOfWeek is provided, modify to the previous occurrence + * of the current day of the week. Use the supplied constants + * to indicate the desired dayOfWeek, ex. static::MONDAY. + * + * @param int|null $dayOfWeek + * + * @return static + */ + public function previous($dayOfWeek = null) + { + if ($dayOfWeek === null) { + $dayOfWeek = $this->dayOfWeek; + } + + return $this->startOfDay()->modify('last '.static::$days[$dayOfWeek]); + } + + /** + * Modify to the first occurrence of a given day of the week + * in the current month. If no dayOfWeek is provided, modify to the + * first day of the current month. Use the supplied constants + * to indicate the desired dayOfWeek, ex. static::MONDAY. + * + * @param int|null $dayOfWeek + * + * @return static + */ + public function firstOfMonth($dayOfWeek = null) + { + $this->startOfDay(); + + if ($dayOfWeek === null) { + return $this->day(1); + } + + return $this->modify('first '.static::$days[$dayOfWeek].' of '.$this->format('F').' '.$this->year); + } + + /** + * Modify to the last occurrence of a given day of the week + * in the current month. If no dayOfWeek is provided, modify to the + * last day of the current month. Use the supplied constants + * to indicate the desired dayOfWeek, ex. static::MONDAY. + * + * @param int|null $dayOfWeek + * + * @return static + */ + public function lastOfMonth($dayOfWeek = null) + { + $this->startOfDay(); + + if ($dayOfWeek === null) { + return $this->day($this->daysInMonth); + } + + return $this->modify('last '.static::$days[$dayOfWeek].' of '.$this->format('F').' '.$this->year); + } + + /** + * Modify to the given occurrence of a given day of the week + * in the current month. If the calculated occurrence is outside the scope + * of the current month, then return false and no modifications are made. + * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY. + * + * @param int $nth + * @param int $dayOfWeek + * + * @return mixed + */ + public function nthOfMonth($nth, $dayOfWeek) + { + $date = $this->copy()->firstOfMonth(); + $check = $date->format('Y-m'); + $date->modify('+'.$nth.' '.static::$days[$dayOfWeek]); + + return $date->format('Y-m') === $check ? $this->modify($date) : false; + } + + /** + * Modify to the first occurrence of a given day of the week + * in the current quarter. If no dayOfWeek is provided, modify to the + * first day of the current quarter. Use the supplied constants + * to indicate the desired dayOfWeek, ex. static::MONDAY. + * + * @param int|null $dayOfWeek day of the week default null + * + * @return static + */ + public function firstOfQuarter($dayOfWeek = null) + { + return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER - 2, 1)->firstOfMonth($dayOfWeek); + } + + /** + * Modify to the last occurrence of a given day of the week + * in the current quarter. If no dayOfWeek is provided, modify to the + * last day of the current quarter. Use the supplied constants + * to indicate the desired dayOfWeek, ex. static::MONDAY. + * + * @param int|null $dayOfWeek day of the week default null + * + * @return static + */ + public function lastOfQuarter($dayOfWeek = null) + { + return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER, 1)->lastOfMonth($dayOfWeek); + } + + /** + * Modify to the given occurrence of a given day of the week + * in the current quarter. If the calculated occurrence is outside the scope + * of the current quarter, then return false and no modifications are made. + * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY. + * + * @param int $nth + * @param int $dayOfWeek + * + * @return mixed + */ + public function nthOfQuarter($nth, $dayOfWeek) + { + $date = $this->copy()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER); + $lastMonth = $date->month; + $year = $date->year; + $date->firstOfQuarter()->modify('+'.$nth.' '.static::$days[$dayOfWeek]); + + return ($lastMonth < $date->month || $year !== $date->year) ? false : $this->modify($date); + } + + /** + * Modify to the first occurrence of a given day of the week + * in the current year. If no dayOfWeek is provided, modify to the + * first day of the current year. Use the supplied constants + * to indicate the desired dayOfWeek, ex. static::MONDAY. + * + * @param int|null $dayOfWeek day of the week default null + * + * @return static + */ + public function firstOfYear($dayOfWeek = null) + { + return $this->month(1)->firstOfMonth($dayOfWeek); + } + + /** + * Modify to the last occurrence of a given day of the week + * in the current year. If no dayOfWeek is provided, modify to the + * last day of the current year. Use the supplied constants + * to indicate the desired dayOfWeek, ex. static::MONDAY. + * + * @param int|null $dayOfWeek day of the week default null + * + * @return static + */ + public function lastOfYear($dayOfWeek = null) + { + return $this->month(static::MONTHS_PER_YEAR)->lastOfMonth($dayOfWeek); + } + + /** + * Modify to the given occurrence of a given day of the week + * in the current year. If the calculated occurrence is outside the scope + * of the current year, then return false and no modifications are made. + * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY. + * + * @param int $nth + * @param int $dayOfWeek + * + * @return mixed + */ + public function nthOfYear($nth, $dayOfWeek) + { + $date = $this->copy()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]); + + return $this->year === $date->year ? $this->modify($date) : false; + } + + /** + * Modify the current instance to the average of a given instance (default now) and the current instance. + * + * @param \Carbon\Carbon|\DateTimeInterface|string|null $date + * + * @return static + */ + public function average($date = null) + { + $date = $this->resolveCarbon($date); + $increment = $this->diffInRealSeconds($date, false) / 2; + $intIncrement = floor($increment); + $microIncrement = (int) (($date->micro - $this->micro) / 2 + 1000000 * ($increment - $intIncrement)); + $micro = (int) ($this->micro + $microIncrement); + while ($micro >= 1000000) { + $micro -= 1000000; + $intIncrement++; + } + $this->addSeconds($intIncrement); + + if (version_compare(PHP_VERSION, '7.1.8-dev', '>=')) { + $this->setTime($this->hour, $this->minute, $this->second, $micro); + } + + return $this; + } + + /////////////////////////////////////////////////////////////////// + /////////////////////////// SERIALIZATION ///////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Return a serialized string of the instance. + * + * @return string + */ + public function serialize() + { + return serialize($this); + } + + /** + * Create an instance from a serialized string. + * + * @param string $value + * + * @throws \InvalidArgumentException + * + * @return static + */ + public static function fromSerialized($value) + { + $instance = @unserialize($value); + + if (!$instance instanceof static) { + throw new InvalidArgumentException('Invalid serialized value.'); + } + + return $instance; + } + + /** + * The __set_state handler. + * + * @param array $array + * + * @return static + */ + public static function __set_state($array) + { + return static::instance(parent::__set_state($array)); + } + + /** + * Prepare the object for JSON serialization. + * + * @return array|string + */ + public function jsonSerialize() + { + if (static::$serializer) { + return call_user_func(static::$serializer, $this); + } + + $carbon = $this; + + return call_user_func(function () use ($carbon) { + return get_object_vars($carbon); + }); + } + + /** + * JSON serialize all Carbon instances using the given callback. + * + * @param callable $callback + * + * @return void + */ + public static function serializeUsing($callback) + { + static::$serializer = $callback; + } + + /////////////////////////////////////////////////////////////////// + /////////////////////////////// MACRO ///////////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Register a custom macro. + * + * @param string $name + * @param object|callable $macro + * + * @return void + */ + public static function macro($name, $macro) + { + static::$localMacros[$name] = $macro; + } + + /** + * Remove all macros. + */ + public static function resetMacros() + { + static::$localMacros = array(); + } + + /** + * Mix another object into the class. + * + * @param object $mixin + * + * @return void + */ + public static function mixin($mixin) + { + $reflection = new \ReflectionClass($mixin); + $methods = $reflection->getMethods( + \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED + ); + + foreach ($methods as $method) { + $method->setAccessible(true); + + static::macro($method->name, $method->invoke($mixin)); + } + } + + /** + * Checks if macro is registered. + * + * @param string $name + * + * @return bool + */ + public static function hasMacro($name) + { + return isset(static::$localMacros[$name]); + } + + /** + * Dynamically handle calls to the class. + * + * @param string $method + * @param array $parameters + * + * @throws \BadMethodCallException + * + * @return mixed + */ + public static function __callStatic($method, $parameters) + { + if (!static::hasMacro($method)) { + throw new \BadMethodCallException("Method $method does not exist."); + } + + if (static::$localMacros[$method] instanceof Closure && method_exists('Closure', 'bind')) { + return call_user_func_array(Closure::bind(static::$localMacros[$method], null, get_called_class()), $parameters); + } + + return call_user_func_array(static::$localMacros[$method], $parameters); + } + + /** + * Dynamically handle calls to the class. + * + * @param string $method + * @param array $parameters + * + * @throws \BadMethodCallException|\ReflectionException + * + * @return mixed + */ + public function __call($method, $parameters) + { + if (!static::hasMacro($method)) { + throw new \BadMethodCallException("Method $method does not exist."); + } + + $macro = static::$localMacros[$method]; + + $reflexion = new \ReflectionFunction($macro); + $reflectionParameters = $reflexion->getParameters(); + $expectedCount = count($reflectionParameters); + $actualCount = count($parameters); + if ($expectedCount > $actualCount && $reflectionParameters[$expectedCount - 1]->name === 'self') { + for ($i = $actualCount; $i < $expectedCount - 1; $i++) { + $parameters[] = $reflectionParameters[$i]->getDefaultValue(); + } + $parameters[] = $this; + } + + if ($macro instanceof Closure && method_exists($macro, 'bindTo')) { + return call_user_func_array($macro->bindTo($this, get_class($this)), $parameters); + } + + return call_user_func_array($macro, $parameters); + } + + /** + * Show truthy properties on var_dump(). + * + * @return array + */ + public function __debugInfo() + { + return array_filter(get_object_vars($this), function ($var) { + return $var; + }); + } + + /** + * Cast the current instance into the given class. + * + * @param string $className The $className::instance() method will be called to cast the current object. + * + * @return object + */ + public function cast($className) + { + if (!method_exists($className, 'instance')) { + throw new \InvalidArgumentException("$className has not the instance() method needed to cast the date."); + } + + return $className::instance($this); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php new file mode 100644 index 0000000..e8c6032 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php @@ -0,0 +1,1163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Carbon; + +use Closure; +use DateInterval; +use InvalidArgumentException; +use ReflectionClass; +use ReflectionFunction; +use ReflectionMethod; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * A simple API extension for DateInterval. + * The implementation provides helpers to handle weeks but only days are saved. + * Weeks are calculated based on the total days of the current instance. + * + * @property int $years Total years of the current interval. + * @property int $months Total months of the current interval. + * @property int $weeks Total weeks of the current interval calculated from the days. + * @property int $dayz Total days of the current interval (weeks * 7 + days). + * @property int $hours Total hours of the current interval. + * @property int $minutes Total minutes of the current interval. + * @property int $seconds Total seconds of the current interval. + * @property-read int $dayzExcludeWeeks Total days remaining in the final week of the current instance (days % 7). + * @property-read int $daysExcludeWeeks alias of dayzExcludeWeeks + * @property-read float $totalYears Number of years equivalent to the interval. + * @property-read float $totalMonths Number of months equivalent to the interval. + * @property-read float $totalWeeks Number of weeks equivalent to the interval. + * @property-read float $totalDays Number of days equivalent to the interval. + * @property-read float $totalDayz Alias for totalDays. + * @property-read float $totalHours Number of hours equivalent to the interval. + * @property-read float $totalMinutes Number of minutes equivalent to the interval. + * @property-read float $totalSeconds Number of seconds equivalent to the interval. + * + * @method static CarbonInterval years($years = 1) Create instance specifying a number of years. + * @method static CarbonInterval year($years = 1) Alias for years() + * @method static CarbonInterval months($months = 1) Create instance specifying a number of months. + * @method static CarbonInterval month($months = 1) Alias for months() + * @method static CarbonInterval weeks($weeks = 1) Create instance specifying a number of weeks. + * @method static CarbonInterval week($weeks = 1) Alias for weeks() + * @method static CarbonInterval days($days = 1) Create instance specifying a number of days. + * @method static CarbonInterval dayz($days = 1) Alias for days() + * @method static CarbonInterval day($days = 1) Alias for days() + * @method static CarbonInterval hours($hours = 1) Create instance specifying a number of hours. + * @method static CarbonInterval hour($hours = 1) Alias for hours() + * @method static CarbonInterval minutes($minutes = 1) Create instance specifying a number of minutes. + * @method static CarbonInterval minute($minutes = 1) Alias for minutes() + * @method static CarbonInterval seconds($seconds = 1) Create instance specifying a number of seconds. + * @method static CarbonInterval second($seconds = 1) Alias for seconds() + * @method CarbonInterval years($years = 1) Set the years portion of the current interval. + * @method CarbonInterval year($years = 1) Alias for years(). + * @method CarbonInterval months($months = 1) Set the months portion of the current interval. + * @method CarbonInterval month($months = 1) Alias for months(). + * @method CarbonInterval weeks($weeks = 1) Set the weeks portion of the current interval. Will overwrite dayz value. + * @method CarbonInterval week($weeks = 1) Alias for weeks(). + * @method CarbonInterval days($days = 1) Set the days portion of the current interval. + * @method CarbonInterval dayz($days = 1) Alias for days(). + * @method CarbonInterval day($days = 1) Alias for days(). + * @method CarbonInterval hours($hours = 1) Set the hours portion of the current interval. + * @method CarbonInterval hour($hours = 1) Alias for hours(). + * @method CarbonInterval minutes($minutes = 1) Set the minutes portion of the current interval. + * @method CarbonInterval minute($minutes = 1) Alias for minutes(). + * @method CarbonInterval seconds($seconds = 1) Set the seconds portion of the current interval. + * @method CarbonInterval second($seconds = 1) Alias for seconds(). + */ +class CarbonInterval extends DateInterval +{ + /** + * Interval spec period designators + */ + const PERIOD_PREFIX = 'P'; + const PERIOD_YEARS = 'Y'; + const PERIOD_MONTHS = 'M'; + const PERIOD_DAYS = 'D'; + const PERIOD_TIME_PREFIX = 'T'; + const PERIOD_HOURS = 'H'; + const PERIOD_MINUTES = 'M'; + const PERIOD_SECONDS = 'S'; + + /** + * A translator to ... er ... translate stuff + * + * @var \Symfony\Component\Translation\TranslatorInterface + */ + protected static $translator; + + /** + * @var array|null + */ + protected static $cascadeFactors; + + /** + * @var array|null + */ + private static $flipCascadeFactors; + + /** + * The registered macros. + * + * @var array + */ + protected static $macros = array(); + + /** + * Before PHP 5.4.20/5.5.4 instead of FALSE days will be set to -99999 when the interval instance + * was created by DateTime::diff(). + */ + const PHP_DAYS_FALSE = -99999; + + /** + * Mapping of units and factors for cascading. + * + * Should only be modified by changing the factors or referenced constants. + * + * @return array + */ + public static function getCascadeFactors() + { + return static::$cascadeFactors ?: array( + 'minutes' => array(Carbon::SECONDS_PER_MINUTE, 'seconds'), + 'hours' => array(Carbon::MINUTES_PER_HOUR, 'minutes'), + 'dayz' => array(Carbon::HOURS_PER_DAY, 'hours'), + 'months' => array(Carbon::DAYS_PER_WEEK * Carbon::WEEKS_PER_MONTH, 'dayz'), + 'years' => array(Carbon::MONTHS_PER_YEAR, 'months'), + ); + } + + private static function standardizeUnit($unit) + { + $unit = rtrim($unit, 'sz').'s'; + + return $unit === 'days' ? 'dayz' : $unit; + } + + private static function getFlipCascadeFactors() + { + if (!self::$flipCascadeFactors) { + self::$flipCascadeFactors = array(); + foreach (static::getCascadeFactors() as $to => $tuple) { + list($factor, $from) = $tuple; + + self::$flipCascadeFactors[self::standardizeUnit($from)] = array(self::standardizeUnit($to), $factor); + } + } + + return self::$flipCascadeFactors; + } + + /** + * @param array $cascadeFactors + */ + public static function setCascadeFactors(array $cascadeFactors) + { + self::$flipCascadeFactors = null; + static::$cascadeFactors = $cascadeFactors; + } + + /** + * Determine if the interval was created via DateTime:diff() or not. + * + * @param DateInterval $interval + * + * @return bool + */ + private static function wasCreatedFromDiff(DateInterval $interval) + { + return $interval->days !== false && $interval->days !== static::PHP_DAYS_FALSE; + } + + /////////////////////////////////////////////////////////////////// + //////////////////////////// CONSTRUCTORS ///////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Create a new CarbonInterval instance. + * + * @param int $years + * @param int $months + * @param int $weeks + * @param int $days + * @param int $hours + * @param int $minutes + * @param int $seconds + */ + public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null) + { + $spec = $years; + + if (!is_string($spec) || floatval($years) || preg_match('/^[0-9.]/', $years)) { + $spec = static::PERIOD_PREFIX; + + $spec .= $years > 0 ? $years.static::PERIOD_YEARS : ''; + $spec .= $months > 0 ? $months.static::PERIOD_MONTHS : ''; + + $specDays = 0; + $specDays += $weeks > 0 ? $weeks * static::getDaysPerWeek() : 0; + $specDays += $days > 0 ? $days : 0; + + $spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : ''; + + if ($hours > 0 || $minutes > 0 || $seconds > 0) { + $spec .= static::PERIOD_TIME_PREFIX; + $spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : ''; + $spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : ''; + $spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : ''; + } + + if ($spec === static::PERIOD_PREFIX) { + // Allow the zero interval. + $spec .= '0'.static::PERIOD_YEARS; + } + } + + parent::__construct($spec); + } + + /** + * Returns the factor for a given source-to-target couple. + * + * @param string $source + * @param string $target + * + * @return int|null + */ + public static function getFactor($source, $target) + { + $source = self::standardizeUnit($source); + $target = self::standardizeUnit($target); + $factors = static::getFlipCascadeFactors(); + if (isset($factors[$source])) { + list($to, $factor) = $factors[$source]; + if ($to === $target) { + return $factor; + } + } + + return null; + } + + /** + * Returns current config for days per week. + * + * @return int + */ + public static function getDaysPerWeek() + { + return static::getFactor('dayz', 'weeks') ?: Carbon::DAYS_PER_WEEK; + } + + /** + * Returns current config for hours per day. + * + * @return int + */ + public static function getHoursPerDay() + { + return static::getFactor('hours', 'dayz') ?: Carbon::HOURS_PER_DAY; + } + + /** + * Returns current config for minutes per hour. + * + * @return int + */ + public static function getMinutesPerHours() + { + return static::getFactor('minutes', 'hours') ?: Carbon::MINUTES_PER_HOUR; + } + + /** + * Returns current config for seconds per minute. + * + * @return int + */ + public static function getSecondsPerMinutes() + { + return static::getFactor('seconds', 'minutes') ?: Carbon::SECONDS_PER_MINUTE; + } + + /** + * Create a new CarbonInterval instance from specific values. + * This is an alias for the constructor that allows better fluent + * syntax as it allows you to do CarbonInterval::create(1)->fn() rather than + * (new CarbonInterval(1))->fn(). + * + * @param int $years + * @param int $months + * @param int $weeks + * @param int $days + * @param int $hours + * @param int $minutes + * @param int $seconds + * + * @return static + */ + public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null) + { + return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds); + } + + /** + * Get a copy of the instance. + * + * @return static + */ + public function copy() + { + $date = new static($this->spec()); + $date->invert = $this->invert; + + return $date; + } + + /** + * Provide static helpers to create instances. Allows CarbonInterval::years(3). + * + * Note: This is done using the magic method to allow static and instance methods to + * have the same names. + * + * @param string $name + * @param array $args + * + * @return static + */ + public static function __callStatic($name, $args) + { + $arg = count($args) === 0 ? 1 : $args[0]; + + switch ($name) { + case 'years': + case 'year': + return new static($arg); + + case 'months': + case 'month': + return new static(null, $arg); + + case 'weeks': + case 'week': + return new static(null, null, $arg); + + case 'days': + case 'dayz': + case 'day': + return new static(null, null, null, $arg); + + case 'hours': + case 'hour': + return new static(null, null, null, null, $arg); + + case 'minutes': + case 'minute': + return new static(null, null, null, null, null, $arg); + + case 'seconds': + case 'second': + return new static(null, null, null, null, null, null, $arg); + } + + if (static::hasMacro($name)) { + return call_user_func_array( + array(new static(0), $name), $args + ); + } + } + + /** + * Creates a CarbonInterval from string. + * + * Format: + * + * Suffix | Unit | Example | DateInterval expression + * -------|---------|---------|------------------------ + * y | years | 1y | P1Y + * mo | months | 3mo | P3M + * w | weeks | 2w | P2W + * d | days | 28d | P28D + * h | hours | 4h | PT4H + * m | minutes | 12m | PT12M + * s | seconds | 59s | PT59S + * + * e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds. + * + * Special cases: + * - An empty string will return a zero interval + * - Fractions are allowed for weeks, days, hours and minutes and will be converted + * and rounded to the next smaller value (caution: 0.5w = 4d) + * + * @param string $intervalDefinition + * + * @return static + */ + public static function fromString($intervalDefinition) + { + if (empty($intervalDefinition)) { + return new static(0); + } + + $years = 0; + $months = 0; + $weeks = 0; + $days = 0; + $hours = 0; + $minutes = 0; + $seconds = 0; + + $pattern = '/(\d+(?:\.\d+)?)\h*([^\d\h]*)/i'; + preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER); + while ($match = array_shift($parts)) { + list($part, $value, $unit) = $match; + $intValue = intval($value); + $fraction = floatval($value) - $intValue; + switch (strtolower($unit)) { + case 'year': + case 'years': + case 'y': + $years += $intValue; + break; + + case 'month': + case 'months': + case 'mo': + $months += $intValue; + break; + + case 'week': + case 'weeks': + case 'w': + $weeks += $intValue; + if ($fraction) { + $parts[] = array(null, $fraction * static::getDaysPerWeek(), 'd'); + } + break; + + case 'day': + case 'days': + case 'd': + $days += $intValue; + if ($fraction) { + $parts[] = array(null, $fraction * static::getHoursPerDay(), 'h'); + } + break; + + case 'hour': + case 'hours': + case 'h': + $hours += $intValue; + if ($fraction) { + $parts[] = array(null, $fraction * static::getMinutesPerHours(), 'm'); + } + break; + + case 'minute': + case 'minutes': + case 'm': + $minutes += $intValue; + if ($fraction) { + $seconds += round($fraction * static::getSecondsPerMinutes()); + } + break; + + case 'second': + case 'seconds': + case 's': + $seconds += $intValue; + break; + + default: + throw new InvalidArgumentException( + sprintf('Invalid part %s in definition %s', $part, $intervalDefinition) + ); + } + } + + return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds); + } + + /** + * Create a CarbonInterval instance from a DateInterval one. Can not instance + * DateInterval objects created from DateTime::diff() as you can't externally + * set the $days field. + * + * Pass false as second argument to get a microseconds-precise interval. Else + * microseconds in the original interval will not be kept. + * + * @param DateInterval $di + * @param bool $trimMicroseconds (true by default) + * + * @return static + */ + public static function instance(DateInterval $di, $trimMicroseconds = true) + { + $microseconds = $trimMicroseconds || version_compare(PHP_VERSION, '7.1.0-dev', '<') ? 0 : $di->f; + $instance = new static(static::getDateIntervalSpec($di)); + if ($microseconds) { + $instance->f = $microseconds; + } + $instance->invert = $di->invert; + foreach (array('y', 'm', 'd', 'h', 'i', 's') as $unit) { + if ($di->$unit < 0) { + $instance->$unit *= -1; + } + } + + return $instance; + } + + /** + * Make a CarbonInterval instance from given variable if possible. + * + * Always return a new instance. Parse only strings and only these likely to be intervals (skip dates + * and recurrences). Throw an exception for invalid format, but otherwise return null. + * + * @param mixed $var + * + * @return static|null + */ + public static function make($var) + { + if ($var instanceof DateInterval) { + return static::instance($var); + } + + if (is_string($var)) { + $var = trim($var); + + if (substr($var, 0, 1) === 'P') { + return new static($var); + } + + if (preg_match('/^(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+$/i', $var)) { + return static::fromString($var); + } + } + } + + /////////////////////////////////////////////////////////////////// + /////////////////////// LOCALIZATION ////////////////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Initialize the translator instance if necessary. + * + * @return \Symfony\Component\Translation\TranslatorInterface + */ + protected static function translator() + { + if (static::$translator === null) { + static::$translator = Translator::get(); + } + + return static::$translator; + } + + /** + * Get the translator instance in use. + * + * @return \Symfony\Component\Translation\TranslatorInterface + */ + public static function getTranslator() + { + return static::translator(); + } + + /** + * Set the translator instance to use. + * + * @param TranslatorInterface $translator + */ + public static function setTranslator(TranslatorInterface $translator) + { + static::$translator = $translator; + } + + /** + * Get the current translator locale. + * + * @return string + */ + public static function getLocale() + { + return static::translator()->getLocale(); + } + + /** + * Set the current translator locale. + * + * @param string $locale + */ + public static function setLocale($locale) + { + return static::translator()->setLocale($locale) !== false; + } + + /////////////////////////////////////////////////////////////////// + ///////////////////////// GETTERS AND SETTERS ///////////////////// + /////////////////////////////////////////////////////////////////// + + /** + * Get a part of the CarbonInterval object. + * + * @param string $name + * + * @throws \InvalidArgumentException + * + * @return int|float + */ + public function __get($name) + { + if (substr($name, 0, 5) === 'total') { + return $this->total(substr($name, 5)); + } + + switch ($name) { + case 'years': + return $this->y; + + case 'months': + return $this->m; + + case 'dayz': + return $this->d; + + case 'hours': + return $this->h; + + case 'minutes': + return $this->i; + + case 'seconds': + return $this->s; + + case 'weeks': + return (int) floor($this->d / static::getDaysPerWeek()); + + case 'daysExcludeWeeks': + case 'dayzExcludeWeeks': + return $this->d % static::getDaysPerWeek(); + + default: + throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name)); + } + } + + /** + * Set a part of the CarbonInterval object. + * + * @param string $name + * @param int $val + * + * @throws \InvalidArgumentException + */ + public function __set($name, $val) + { + switch ($name) { + case 'years': + $this->y = $val; + break; + + case 'months': + $this->m = $val; + break; + + case 'weeks': + $this->d = $val * static::getDaysPerWeek(); + break; + + case 'dayz': + $this->d = $val; + break; + + case 'hours': + $this->h = $val; + break; + + case 'minutes': + $this->i = $val; + break; + + case 'seconds': + $this->s = $val; + break; + } + } + + /** + * Allow setting of weeks and days to be cumulative. + * + * @param int $weeks Number of weeks to set + * @param int $days Number of days to set + * + * @return static + */ + public function weeksAndDays($weeks, $days) + { + $this->dayz = ($weeks * static::getDaysPerWeek()) + $days; + + return $this; + } + + /** + * Register a custom macro. + * + * @param string $name + * @param object|callable $macro + * + * @return void + */ + public static function macro($name, $macro) + { + static::$macros[$name] = $macro; + } + + /** + * Remove all macros. + */ + public static function resetMacros() + { + static::$macros = array(); + } + + /** + * Register macros from a mixin object. + * + * @param object $mixin + * + * @throws \ReflectionException + * + * @return void + */ + public static function mixin($mixin) + { + $reflection = new ReflectionClass($mixin); + + $methods = $reflection->getMethods( + ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED + ); + + foreach ($methods as $method) { + $method->setAccessible(true); + + static::macro($method->name, $method->invoke($mixin)); + } + } + + /** + * Check if macro is registered. + * + * @param string $name + * + * @return bool + */ + public static function hasMacro($name) + { + return isset(static::$macros[$name]); + } + + /** + * Call given macro. + * + * @param string $name + * @param array $parameters + * + * @return mixed + */ + protected function callMacro($name, $parameters) + { + $macro = static::$macros[$name]; + + $reflection = new ReflectionFunction($macro); + + $reflectionParameters = $reflection->getParameters(); + + $expectedCount = count($reflectionParameters); + $actualCount = count($parameters); + + if ($expectedCount > $actualCount && $reflectionParameters[$expectedCount - 1]->name === 'self') { + for ($i = $actualCount; $i < $expectedCount - 1; $i++) { + $parameters[] = $reflectionParameters[$i]->getDefaultValue(); + } + + $parameters[] = $this; + } + + if ($macro instanceof Closure && method_exists($macro, 'bindTo')) { + $macro = $macro->bindTo($this, get_class($this)); + } + + return call_user_func_array($macro, $parameters); + } + + /** + * Allow fluent calls on the setters... CarbonInterval::years(3)->months(5)->day(). + * + * Note: This is done using the magic method to allow static and instance methods to + * have the same names. + * + * @param string $name + * @param array $args + * + * @return static + */ + public function __call($name, $args) + { + if (static::hasMacro($name)) { + return $this->callMacro($name, $args); + } + + $arg = count($args) === 0 ? 1 : $args[0]; + + switch ($name) { + case 'years': + case 'year': + $this->years = $arg; + break; + + case 'months': + case 'month': + $this->months = $arg; + break; + + case 'weeks': + case 'week': + $this->dayz = $arg * static::getDaysPerWeek(); + break; + + case 'days': + case 'dayz': + case 'day': + $this->dayz = $arg; + break; + + case 'hours': + case 'hour': + $this->hours = $arg; + break; + + case 'minutes': + case 'minute': + $this->minutes = $arg; + break; + + case 'seconds': + case 'second': + $this->seconds = $arg; + break; + } + + return $this; + } + + /** + * Get the current interval in a human readable format in the current locale. + * + * @param bool $short (false by default), returns short units if true + * + * @return string + */ + public function forHumans($short = false) + { + $periods = array( + 'year' => array('y', $this->years), + 'month' => array('m', $this->months), + 'week' => array('w', $this->weeks), + 'day' => array('d', $this->daysExcludeWeeks), + 'hour' => array('h', $this->hours), + 'minute' => array('min', $this->minutes), + 'second' => array('s', $this->seconds), + ); + + $parts = array(); + foreach ($periods as $unit => $options) { + list($shortUnit, $count) = $options; + if ($count > 0) { + $parts[] = static::translator()->transChoice($short ? $shortUnit : $unit, $count, array(':count' => $count)); + } + } + + return implode(' ', $parts); + } + + /** + * Format the instance as a string using the forHumans() function. + * + * @return string + */ + public function __toString() + { + return $this->forHumans(); + } + + /** + * Convert the interval to a CarbonPeriod. + * + * @return CarbonPeriod + */ + public function toPeriod() + { + return CarbonPeriod::createFromArray( + array_merge(array($this), func_get_args()) + ); + } + + /** + * Invert the interval. + * + * @return $this + */ + public function invert() + { + $this->invert = $this->invert ? 0 : 1; + + return $this; + } + + /** + * Add the passed interval to the current instance. + * + * @param DateInterval $interval + * + * @return static + */ + public function add(DateInterval $interval) + { + $sign = ($this->invert === 1) !== ($interval->invert === 1) ? -1 : 1; + + if (static::wasCreatedFromDiff($interval)) { + $this->dayz += $interval->days * $sign; + } else { + $this->years += $interval->y * $sign; + $this->months += $interval->m * $sign; + $this->dayz += $interval->d * $sign; + $this->hours += $interval->h * $sign; + $this->minutes += $interval->i * $sign; + $this->seconds += $interval->s * $sign; + } + + if (($this->years || $this->months || $this->dayz || $this->hours || $this->minutes || $this->seconds) && + $this->years <= 0 && $this->months <= 0 && $this->dayz <= 0 && $this->hours <= 0 && $this->minutes <= 0 && $this->seconds <= 0 + ) { + $this->years *= -1; + $this->months *= -1; + $this->dayz *= -1; + $this->hours *= -1; + $this->minutes *= -1; + $this->seconds *= -1; + $this->invert(); + } + + return $this; + } + + /** + * Multiply current instance given number of times + * + * @param float $factor + * + * @return $this + */ + public function times($factor) + { + if ($factor < 0) { + $this->invert = $this->invert ? 0 : 1; + $factor = -$factor; + } + + $this->years = (int) round($this->years * $factor); + $this->months = (int) round($this->months * $factor); + $this->dayz = (int) round($this->dayz * $factor); + $this->hours = (int) round($this->hours * $factor); + $this->minutes = (int) round($this->minutes * $factor); + $this->seconds = (int) round($this->seconds * $factor); + + return $this; + } + + /** + * Get the interval_spec string of a date interval. + * + * @param DateInterval $interval + * + * @return string + */ + public static function getDateIntervalSpec(DateInterval $interval) + { + $date = array_filter(array( + static::PERIOD_YEARS => abs($interval->y), + static::PERIOD_MONTHS => abs($interval->m), + static::PERIOD_DAYS => abs($interval->d), + )); + + $time = array_filter(array( + static::PERIOD_HOURS => abs($interval->h), + static::PERIOD_MINUTES => abs($interval->i), + static::PERIOD_SECONDS => abs($interval->s), + )); + + $specString = static::PERIOD_PREFIX; + + foreach ($date as $key => $value) { + $specString .= $value.$key; + } + + if (count($time) > 0) { + $specString .= static::PERIOD_TIME_PREFIX; + foreach ($time as $key => $value) { + $specString .= $value.$key; + } + } + + return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString; + } + + /** + * Get the interval_spec string. + * + * @return string + */ + public function spec() + { + return static::getDateIntervalSpec($this); + } + + /** + * Comparing 2 date intervals. + * + * @param DateInterval $a + * @param DateInterval $b + * + * @return int + */ + public static function compareDateIntervals(DateInterval $a, DateInterval $b) + { + $current = Carbon::now(); + $passed = $current->copy()->add($b); + $current->add($a); + + if ($current < $passed) { + return -1; + } + if ($current > $passed) { + return 1; + } + + return 0; + } + + /** + * Comparing with passed interval. + * + * @param DateInterval $interval + * + * @return int + */ + public function compare(DateInterval $interval) + { + return static::compareDateIntervals($this, $interval); + } + + /** + * Convert overflowed values into bigger units. + * + * @return $this + */ + public function cascade() + { + foreach (static::getFlipCascadeFactors() as $source => $cascade) { + list($target, $factor) = $cascade; + + if ($source === 'dayz' && $target === 'weeks') { + continue; + } + + $value = $this->$source; + $this->$source = $modulo = $value % $factor; + $this->$target += ($value - $modulo) / $factor; + } + + return $this; + } + + /** + * Get amount of given unit equivalent to the interval. + * + * @param string $unit + * + * @throws \InvalidArgumentException + * + * @return float + */ + public function total($unit) + { + $realUnit = $unit = strtolower($unit); + + if (in_array($unit, array('days', 'weeks'))) { + $realUnit = 'dayz'; + } elseif (!in_array($unit, array('seconds', 'minutes', 'hours', 'dayz', 'months', 'years'))) { + throw new InvalidArgumentException("Unknown unit '$unit'."); + } + + $result = 0; + $cumulativeFactor = 0; + $unitFound = false; + + foreach (static::getFlipCascadeFactors() as $source => $cascade) { + list($target, $factor) = $cascade; + + if ($source === $realUnit) { + $unitFound = true; + $result += $this->$source; + $cumulativeFactor = 1; + } + + if ($factor === false) { + if ($unitFound) { + break; + } + + $result = 0; + $cumulativeFactor = 0; + + continue; + } + + if ($target === $realUnit) { + $unitFound = true; + } + + if ($cumulativeFactor) { + $cumulativeFactor *= $factor; + $result += $this->$target * $cumulativeFactor; + + continue; + } + + $result = ($result + $this->$source) / $factor; + } + + if (isset($target) && !$cumulativeFactor) { + $result += $this->$target; + } + + if (!$unitFound) { + throw new \InvalidArgumentException("Unit $unit have no configuration to get total from other units."); + } + + if ($unit === 'weeks') { + return $result / static::getDaysPerWeek(); + } + + return $result; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php new file mode 100644 index 0000000..808e9d6 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php @@ -0,0 +1,1453 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Carbon; + +use BadMethodCallException; +use Closure; +use Countable; +use DateInterval; +use DateTime; +use DateTimeInterface; +use InvalidArgumentException; +use Iterator; +use ReflectionClass; +use ReflectionFunction; +use ReflectionMethod; +use RuntimeException; + +/** + * Substitution of DatePeriod with some modifications and many more features. + * Fully compatible with PHP 5.3+! + * + * @method static CarbonPeriod start($date, $inclusive = null) Create instance specifying start date. + * @method static CarbonPeriod since($date, $inclusive = null) Alias for start(). + * @method static CarbonPeriod sinceNow($inclusive = null) Create instance with start date set to now. + * @method static CarbonPeriod end($date = null, $inclusive = null) Create instance specifying end date. + * @method static CarbonPeriod until($date = null, $inclusive = null) Alias for end(). + * @method static CarbonPeriod untilNow($inclusive = null) Create instance with end date set to now. + * @method static CarbonPeriod dates($start, $end = null) Create instance with start and end date. + * @method static CarbonPeriod between($start, $end = null) Create instance with start and end date. + * @method static CarbonPeriod recurrences($recurrences = null) Create instance with maximum number of recurrences. + * @method static CarbonPeriod times($recurrences = null) Alias for recurrences(). + * @method static CarbonPeriod options($options = null) Create instance with options. + * @method static CarbonPeriod toggle($options, $state = null) Create instance with options toggled on or off. + * @method static CarbonPeriod filter($callback, $name = null) Create instance with filter added to the stack. + * @method static CarbonPeriod push($callback, $name = null) Alias for filter(). + * @method static CarbonPeriod prepend($callback, $name = null) Create instance with filter prepened to the stack. + * @method static CarbonPeriod filters(array $filters) Create instance with filters stack. + * @method static CarbonPeriod interval($interval) Create instance with given date interval. + * @method static CarbonPeriod each($interval) Create instance with given date interval. + * @method static CarbonPeriod every($interval) Create instance with given date interval. + * @method static CarbonPeriod step($interval) Create instance with given date interval. + * @method static CarbonPeriod stepBy($interval) Create instance with given date interval. + * @method static CarbonPeriod invert() Create instance with inverted date interval. + * @method static CarbonPeriod years($years = 1) Create instance specifying a number of years for date interval. + * @method static CarbonPeriod year($years = 1) Alias for years(). + * @method static CarbonPeriod months($months = 1) Create instance specifying a number of months for date interval. + * @method static CarbonPeriod month($months = 1) Alias for months(). + * @method static CarbonPeriod weeks($weeks = 1) Create instance specifying a number of weeks for date interval. + * @method static CarbonPeriod week($weeks = 1) Alias for weeks(). + * @method static CarbonPeriod days($days = 1) Create instance specifying a number of days for date interval. + * @method static CarbonPeriod dayz($days = 1) Alias for days(). + * @method static CarbonPeriod day($days = 1) Alias for days(). + * @method static CarbonPeriod hours($hours = 1) Create instance specifying a number of hours for date interval. + * @method static CarbonPeriod hour($hours = 1) Alias for hours(). + * @method static CarbonPeriod minutes($minutes = 1) Create instance specifying a number of minutes for date interval. + * @method static CarbonPeriod minute($minutes = 1) Alias for minutes(). + * @method static CarbonPeriod seconds($seconds = 1) Create instance specifying a number of seconds for date interval. + * @method static CarbonPeriod second($seconds = 1) Alias for seconds(). + * @method CarbonPeriod start($date, $inclusive = null) Change the period start date. + * @method CarbonPeriod since($date, $inclusive = null) Alias for start(). + * @method CarbonPeriod sinceNow($inclusive = null) Change the period start date to now. + * @method CarbonPeriod end($date = null, $inclusive = null) Change the period end date. + * @method CarbonPeriod until($date = null, $inclusive = null) Alias for end(). + * @method CarbonPeriod untilNow($inclusive = null) Change the period end date to now. + * @method CarbonPeriod dates($start, $end = null) Change the period start and end date. + * @method CarbonPeriod recurrences($recurrences = null) Change the maximum number of recurrences. + * @method CarbonPeriod times($recurrences = null) Alias for recurrences(). + * @method CarbonPeriod options($options = null) Change the period options. + * @method CarbonPeriod toggle($options, $state = null) Toggle given options on or off. + * @method CarbonPeriod filter($callback, $name = null) Add a filter to the stack. + * @method CarbonPeriod push($callback, $name = null) Alias for filter(). + * @method CarbonPeriod prepend($callback, $name = null) Prepend a filter to the stack. + * @method CarbonPeriod filters(array $filters = array()) Set filters stack. + * @method CarbonPeriod interval($interval) Change the period date interval. + * @method CarbonPeriod invert() Invert the period date interval. + * @method CarbonPeriod years($years = 1) Set the years portion of the date interval. + * @method CarbonPeriod year($years = 1) Alias for years(). + * @method CarbonPeriod months($months = 1) Set the months portion of the date interval. + * @method CarbonPeriod month($months = 1) Alias for months(). + * @method CarbonPeriod weeks($weeks = 1) Set the weeks portion of the date interval. + * @method CarbonPeriod week($weeks = 1) Alias for weeks(). + * @method CarbonPeriod days($days = 1) Set the days portion of the date interval. + * @method CarbonPeriod dayz($days = 1) Alias for days(). + * @method CarbonPeriod day($days = 1) Alias for days(). + * @method CarbonPeriod hours($hours = 1) Set the hours portion of the date interval. + * @method CarbonPeriod hour($hours = 1) Alias for hours(). + * @method CarbonPeriod minutes($minutes = 1) Set the minutes portion of the date interval. + * @method CarbonPeriod minute($minutes = 1) Alias for minutes(). + * @method CarbonPeriod seconds($seconds = 1) Set the seconds portion of the date interval. + * @method CarbonPeriod second($seconds = 1) Alias for seconds(). + */ +class CarbonPeriod implements Iterator, Countable +{ + /** + * Built-in filters. + * + * @var string + */ + const RECURRENCES_FILTER = 'Carbon\CarbonPeriod::filterRecurrences'; + const END_DATE_FILTER = 'Carbon\CarbonPeriod::filterEndDate'; + + /** + * Special value which can be returned by filters to end iteration. Also a filter. + * + * @var string + */ + const END_ITERATION = 'Carbon\CarbonPeriod::endIteration'; + + /** + * Available options. + * + * @var int + */ + const EXCLUDE_START_DATE = 1; + const EXCLUDE_END_DATE = 2; + + /** + * Number of maximum attempts before giving up on finding next valid date. + * + * @var int + */ + const NEXT_MAX_ATTEMPTS = 1000; + + /** + * The registered macros. + * + * @var array + */ + protected static $macros = array(); + + /** + * Underlying date interval instance. Always present, one day by default. + * + * @var CarbonInterval + */ + protected $dateInterval; + + /** + * Whether current date interval was set by default. + * + * @var bool + */ + protected $isDefaultInterval; + + /** + * The filters stack. + * + * @var array + */ + protected $filters = array(); + + /** + * Period start date. Applied on rewind. Always present, now by default. + * + * @var Carbon + */ + protected $startDate; + + /** + * Period end date. For inverted interval should be before the start date. Applied via a filter. + * + * @var Carbon|null + */ + protected $endDate; + + /** + * Limit for number of recurrences. Applied via a filter. + * + * @var int|null + */ + protected $recurrences; + + /** + * Iteration options. + * + * @var int + */ + protected $options; + + /** + * Index of current date. Always sequential, even if some dates are skipped by filters. + * Equal to null only before the first iteration. + * + * @var int + */ + protected $key; + + /** + * Current date. May temporarily hold unaccepted value when looking for a next valid date. + * Equal to null only before the first iteration. + * + * @var Carbon + */ + protected $current; + + /** + * Timezone of current date. Taken from the start date. + * + * @var \DateTimeZone|null + */ + protected $timezone; + + /** + * The cached validation result for current date. + * + * @var bool|string|null + */ + protected $validationResult; + + /** + * Create a new instance. + * + * @return static + */ + public static function create() + { + return static::createFromArray(func_get_args()); + } + + /** + * Create a new instance from an array of parameters. + * + * @param array $params + * + * @return static + */ + public static function createFromArray(array $params) + { + // PHP 5.3 equivalent of new static(...$params). + $reflection = new ReflectionClass(get_class()); + /** @var static $instance */ + $instance = $reflection->newInstanceArgs($params); + + return $instance; + } + + /** + * Create CarbonPeriod from ISO 8601 string. + * + * @param string $iso + * @param int|null $options + * + * @return static + */ + public static function createFromIso($iso, $options = null) + { + $params = static::parseIso8601($iso); + + $instance = static::createFromArray($params); + + if ($options !== null) { + $instance->setOptions($options); + } + + return $instance; + } + + /** + * Return whether given interval contains non zero value of any time unit. + * + * @param \DateInterval $interval + * + * @return bool + */ + protected static function intervalHasTime(DateInterval $interval) + { + // The array_key_exists and get_object_vars are used as a workaround to check microsecond support. + // Both isset and property_exists will fail on PHP 7.0.14 - 7.0.21 due to the following bug: + // https://bugs.php.net/bug.php?id=74852 + return $interval->h || $interval->i || $interval->s || array_key_exists('f', get_object_vars($interval)) && $interval->f; + } + + /** + * Return whether given callable is a string pointing to one of Carbon's is* methods + * and should be automatically converted to a filter callback. + * + * @param callable $callable + * + * @return bool + */ + protected static function isCarbonPredicateMethod($callable) + { + return is_string($callable) && substr($callable, 0, 2) === 'is' && (method_exists('Carbon\Carbon', $callable) || Carbon::hasMacro($callable)); + } + + /** + * Return whether given variable is an ISO 8601 specification. + * + * Note: Check is very basic, as actual validation will be done later when parsing. + * We just want to ensure that variable is not any other type of a valid parameter. + * + * @param mixed $var + * + * @return bool + */ + protected static function isIso8601($var) + { + if (!is_string($var)) { + return false; + } + + // Match slash but not within a timezone name. + $part = '[a-z]+(?:[_-][a-z]+)*'; + + preg_match("#\b$part/$part\b|(/)#i", $var, $match); + + return isset($match[1]); + } + + /** + * Parse given ISO 8601 string into an array of arguments. + * + * @param string $iso + * + * @return array + */ + protected static function parseIso8601($iso) + { + $result = array(); + + $interval = null; + $start = null; + $end = null; + + foreach (explode('/', $iso) as $key => $part) { + if ($key === 0 && preg_match('/^R([0-9]*)$/', $part, $match)) { + $parsed = strlen($match[1]) ? (int) $match[1] : null; + } elseif ($interval === null && $parsed = CarbonInterval::make($part)) { + $interval = $part; + } elseif ($start === null && $parsed = Carbon::make($part)) { + $start = $part; + } elseif ($end === null && $parsed = Carbon::make(static::addMissingParts($start, $part))) { + $end = $part; + } else { + throw new InvalidArgumentException("Invalid ISO 8601 specification: $iso."); + } + + $result[] = $parsed; + } + + return $result; + } + + /** + * Add missing parts of the target date from the soure date. + * + * @param string $source + * @param string $target + * + * @return string + */ + protected static function addMissingParts($source, $target) + { + $pattern = '/'.preg_replace('/[0-9]+/', '[0-9]+', preg_quote($target, '/')).'$/'; + + $result = preg_replace($pattern, $target, $source, 1, $count); + + return $count ? $result : $target; + } + + /** + * Register a custom macro. + * + * @param string $name + * @param object|callable $macro + * + * @return void + */ + public static function macro($name, $macro) + { + static::$macros[$name] = $macro; + } + + /** + * Remove all macros. + */ + public static function resetMacros() + { + static::$macros = array(); + } + + /** + * Register macros from a mixin object. + * + * @param object $mixin + * + * @throws \ReflectionException + * + * @return void + */ + public static function mixin($mixin) + { + $reflection = new ReflectionClass($mixin); + + $methods = $reflection->getMethods( + ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED + ); + + foreach ($methods as $method) { + $method->setAccessible(true); + + static::macro($method->name, $method->invoke($mixin)); + } + } + + /** + * Check if macro is registered. + * + * @param string $name + * + * @return bool + */ + public static function hasMacro($name) + { + return isset(static::$macros[$name]); + } + + /** + * Provide static proxy for instance aliases. + * + * @param string $method + * @param array $parameters + * + * @return mixed + */ + public static function __callStatic($method, $parameters) + { + return call_user_func_array( + array(new static, $method), $parameters + ); + } + + /** + * CarbonPeriod constructor. + * + * @throws InvalidArgumentException + */ + public function __construct() + { + // Parse and assign arguments one by one. First argument may be an ISO 8601 spec, + // which will be first parsed into parts and then processed the same way. + $arguments = func_get_args(); + + if (count($arguments) && static::isIso8601($iso = $arguments[0])) { + array_splice($arguments, 0, 1, static::parseIso8601($iso)); + } + + foreach ($arguments as $argument) { + if ($this->dateInterval === null && $parsed = CarbonInterval::make($argument)) { + $this->setDateInterval($parsed); + } elseif ($this->startDate === null && $parsed = Carbon::make($argument)) { + $this->setStartDate($parsed); + } elseif ($this->endDate === null && $parsed = Carbon::make($argument)) { + $this->setEndDate($parsed); + } elseif ($this->recurrences === null && $this->endDate === null && is_numeric($argument)) { + $this->setRecurrences($argument); + } elseif ($this->options === null && (is_int($argument) || $argument === null)) { + $this->setOptions($argument); + } else { + throw new InvalidArgumentException('Invalid constructor parameters.'); + } + } + + if ($this->startDate === null) { + $this->setStartDate(Carbon::now()); + } + + if ($this->dateInterval === null) { + $this->setDateInterval(CarbonInterval::day()); + + $this->isDefaultInterval = true; + } + + if ($this->options === null) { + $this->setOptions(0); + } + } + + /** + * Change the period date interval. + * + * @param DateInterval|string $interval + * + * @throws \InvalidArgumentException + * + * @return $this + */ + public function setDateInterval($interval) + { + if (!$interval = CarbonInterval::make($interval)) { + throw new InvalidArgumentException('Invalid interval.'); + } + + if ($interval->spec() === 'PT0S') { + throw new InvalidArgumentException('Empty interval is not accepted.'); + } + + $this->dateInterval = $interval; + + $this->isDefaultInterval = false; + + $this->handleChangedParameters(); + + return $this; + } + + /** + * Invert the period date interval. + * + * @return $this + */ + public function invertDateInterval() + { + $interval = $this->dateInterval->invert(); + + return $this->setDateInterval($interval); + } + + /** + * Set start and end date. + * + * @param DateTime|DateTimeInterface|string $start + * @param DateTime|DateTimeInterface|string|null $end + * + * @return $this + */ + public function setDates($start, $end) + { + $this->setStartDate($start); + $this->setEndDate($end); + + return $this; + } + + /** + * Change the period options. + * + * @param int|null $options + * + * @throws \InvalidArgumentException + * + * @return $this + */ + public function setOptions($options) + { + if (!is_int($options) && !is_null($options)) { + throw new InvalidArgumentException('Invalid options.'); + } + + $this->options = $options ?: 0; + + $this->handleChangedParameters(); + + return $this; + } + + /** + * Get the period options. + * + * @return int + */ + public function getOptions() + { + return $this->options; + } + + /** + * Toggle given options on or off. + * + * @param int $options + * @param bool|null $state + * + * @throws \InvalidArgumentException + * + * @return $this + */ + public function toggleOptions($options, $state = null) + { + if ($state === null) { + $state = ($this->options & $options) !== $options; + } + + return $this->setOptions($state ? + $this->options | $options : + $this->options & ~$options + ); + } + + /** + * Toggle EXCLUDE_START_DATE option. + * + * @param bool $state + * + * @return $this + */ + public function excludeStartDate($state = true) + { + return $this->toggleOptions(static::EXCLUDE_START_DATE, $state); + } + + /** + * Toggle EXCLUDE_END_DATE option. + * + * @param bool $state + * + * @return $this + */ + public function excludeEndDate($state = true) + { + return $this->toggleOptions(static::EXCLUDE_END_DATE, $state); + } + + /** + * Get the underlying date interval. + * + * @return CarbonInterval + */ + public function getDateInterval() + { + return $this->dateInterval->copy(); + } + + /** + * Get start date of the period. + * + * @return Carbon + */ + public function getStartDate() + { + return $this->startDate->copy(); + } + + /** + * Get end date of the period. + * + * @return Carbon|null + */ + public function getEndDate() + { + if ($this->endDate) { + return $this->endDate->copy(); + } + } + + /** + * Get number of recurrences. + * + * @return int|null + */ + public function getRecurrences() + { + return $this->recurrences; + } + + /** + * Returns true if the start date should be excluded. + * + * @return bool + */ + public function isStartExcluded() + { + return ($this->options & static::EXCLUDE_START_DATE) !== 0; + } + + /** + * Returns true if the end date should be excluded. + * + * @return bool + */ + public function isEndExcluded() + { + return ($this->options & static::EXCLUDE_END_DATE) !== 0; + } + + /** + * Add a filter to the stack. + * + * @param callable $callback + * @param string $name + * + * @return $this + */ + public function addFilter($callback, $name = null) + { + $tuple = $this->createFilterTuple(func_get_args()); + + $this->filters[] = $tuple; + + $this->handleChangedParameters(); + + return $this; + } + + /** + * Prepend a filter to the stack. + * + * @param callable $callback + * @param string $name + * + * @return $this + */ + public function prependFilter($callback, $name = null) + { + $tuple = $this->createFilterTuple(func_get_args()); + + array_unshift($this->filters, $tuple); + + $this->handleChangedParameters(); + + return $this; + } + + /** + * Create a filter tuple from raw parameters. + * + * Will create an automatic filter callback for one of Carbon's is* methods. + * + * @param array $parameters + * + * @return array + */ + protected function createFilterTuple(array $parameters) + { + $method = array_shift($parameters); + + if (!$this->isCarbonPredicateMethod($method)) { + return array($method, array_shift($parameters)); + } + + return array(function ($date) use ($method, $parameters) { + return call_user_func_array(array($date, $method), $parameters); + }, $method); + } + + /** + * Remove a filter by instance or name. + * + * @param callable|string $filter + * + * @return $this + */ + public function removeFilter($filter) + { + $key = is_callable($filter) ? 0 : 1; + + $this->filters = array_values(array_filter( + $this->filters, + function ($tuple) use ($key, $filter) { + return $tuple[$key] !== $filter; + } + )); + + $this->updateInternalState(); + + $this->handleChangedParameters(); + + return $this; + } + + /** + * Return whether given instance or name is in the filter stack. + * + * @param callable|string $filter + * + * @return bool + */ + public function hasFilter($filter) + { + $key = is_callable($filter) ? 0 : 1; + + foreach ($this->filters as $tuple) { + if ($tuple[$key] === $filter) { + return true; + } + } + + return false; + } + + /** + * Get filters stack. + * + * @return array + */ + public function getFilters() + { + return $this->filters; + } + + /** + * Set filters stack. + * + * @param array $filters + * + * @return $this + */ + public function setFilters(array $filters) + { + $this->filters = $filters; + + $this->updateInternalState(); + + $this->handleChangedParameters(); + + return $this; + } + + /** + * Reset filters stack. + * + * @return $this + */ + public function resetFilters() + { + $this->filters = array(); + + if ($this->endDate !== null) { + $this->filters[] = array(static::END_DATE_FILTER, null); + } + + if ($this->recurrences !== null) { + $this->filters[] = array(static::RECURRENCES_FILTER, null); + } + + $this->handleChangedParameters(); + + return $this; + } + + /** + * Update properties after removing built-in filters. + * + * @return void + */ + protected function updateInternalState() + { + if (!$this->hasFilter(static::END_DATE_FILTER)) { + $this->endDate = null; + } + + if (!$this->hasFilter(static::RECURRENCES_FILTER)) { + $this->recurrences = null; + } + } + + /** + * Add a recurrences filter (set maximum number of recurrences). + * + * @param int|null $recurrences + * + * @throws \InvalidArgumentException + * + * @return $this + */ + public function setRecurrences($recurrences) + { + if (!is_numeric($recurrences) && !is_null($recurrences) || $recurrences < 0) { + throw new InvalidArgumentException('Invalid number of recurrences.'); + } + + if ($recurrences === null) { + return $this->removeFilter(static::RECURRENCES_FILTER); + } + + $this->recurrences = (int) $recurrences; + + if (!$this->hasFilter(static::RECURRENCES_FILTER)) { + return $this->addFilter(static::RECURRENCES_FILTER); + } + + $this->handleChangedParameters(); + + return $this; + } + + /** + * Recurrences filter callback (limits number of recurrences). + * + * @param \Carbon\Carbon $current + * @param int $key + * + * @return bool|string + */ + protected function filterRecurrences($current, $key) + { + if ($key < $this->recurrences) { + return true; + } + + return static::END_ITERATION; + } + + /** + * Change the period start date. + * + * @param DateTime|DateTimeInterface|string $date + * @param bool|null $inclusive + * + * @throws \InvalidArgumentException + * + * @return $this + */ + public function setStartDate($date, $inclusive = null) + { + if (!$date = Carbon::make($date)) { + throw new InvalidArgumentException('Invalid start date.'); + } + + $this->startDate = $date; + + if ($inclusive !== null) { + $this->toggleOptions(static::EXCLUDE_START_DATE, !$inclusive); + } + + return $this; + } + + /** + * Change the period end date. + * + * @param DateTime|DateTimeInterface|string|null $date + * @param bool|null $inclusive + * + * @throws \InvalidArgumentException + * + * @return $this + */ + public function setEndDate($date, $inclusive = null) + { + if (!is_null($date) && !$date = Carbon::make($date)) { + throw new InvalidArgumentException('Invalid end date.'); + } + + if (!$date) { + return $this->removeFilter(static::END_DATE_FILTER); + } + + $this->endDate = $date; + + if ($inclusive !== null) { + $this->toggleOptions(static::EXCLUDE_END_DATE, !$inclusive); + } + + if (!$this->hasFilter(static::END_DATE_FILTER)) { + return $this->addFilter(static::END_DATE_FILTER); + } + + $this->handleChangedParameters(); + + return $this; + } + + /** + * End date filter callback. + * + * @param \Carbon\Carbon $current + * + * @return bool|string + */ + protected function filterEndDate($current) + { + if (!$this->isEndExcluded() && $current == $this->endDate) { + return true; + } + + if ($this->dateInterval->invert ? $current > $this->endDate : $current < $this->endDate) { + return true; + } + + return static::END_ITERATION; + } + + /** + * End iteration filter callback. + * + * @return string + */ + protected function endIteration() + { + return static::END_ITERATION; + } + + /** + * Handle change of the parameters. + */ + protected function handleChangedParameters() + { + $this->validationResult = null; + } + + /** + * Validate current date and stop iteration when necessary. + * + * Returns true when current date is valid, false if it is not, or static::END_ITERATION + * when iteration should be stopped. + * + * @return bool|string + */ + protected function validateCurrentDate() + { + if ($this->current === null) { + $this->rewind(); + } + + // Check after the first rewind to avoid repeating the initial validation. + if ($this->validationResult !== null) { + return $this->validationResult; + } + + return $this->validationResult = $this->checkFilters(); + } + + /** + * Check whether current value and key pass all the filters. + * + * @return bool|string + */ + protected function checkFilters() + { + $current = $this->prepareForReturn($this->current); + + foreach ($this->filters as $tuple) { + $result = call_user_func( + $tuple[0], $current->copy(), $this->key, $this + ); + + if ($result === static::END_ITERATION) { + return static::END_ITERATION; + } + + if (!$result) { + return false; + } + } + + return true; + } + + /** + * Prepare given date to be returned to the external logic. + * + * @param Carbon $date + * + * @return Carbon + */ + protected function prepareForReturn(Carbon $date) + { + $date = $date->copy(); + + if ($this->timezone) { + $date->setTimezone($this->timezone); + } + + return $date; + } + + /** + * Check if the current position is valid. + * + * @return bool + */ + public function valid() + { + return $this->validateCurrentDate() === true; + } + + /** + * Return the current key. + * + * @return int|null + */ + public function key() + { + if ($this->valid()) { + return $this->key; + } + } + + /** + * Return the current date. + * + * @return Carbon|null + */ + public function current() + { + if ($this->valid()) { + return $this->prepareForReturn($this->current); + } + } + + /** + * Move forward to the next date. + * + * @throws \RuntimeException + * + * @return void + */ + public function next() + { + if ($this->current === null) { + $this->rewind(); + } + + if ($this->validationResult !== static::END_ITERATION) { + $this->key++; + + $this->incrementCurrentDateUntilValid(); + } + } + + /** + * Rewind to the start date. + * + * Iterating over a date in the UTC timezone avoids bug during backward DST change. + * + * @see https://bugs.php.net/bug.php?id=72255 + * @see https://bugs.php.net/bug.php?id=74274 + * @see https://wiki.php.net/rfc/datetime_and_daylight_saving_time + * + * @throws \RuntimeException + * + * @return void + */ + public function rewind() + { + $this->key = 0; + $this->current = $this->startDate->copy(); + $this->timezone = static::intervalHasTime($this->dateInterval) ? $this->current->getTimezone() : null; + + if ($this->timezone) { + $this->current->setTimezone('UTC'); + } + + $this->validationResult = null; + + if ($this->isStartExcluded() || $this->validateCurrentDate() === false) { + $this->incrementCurrentDateUntilValid(); + } + } + + /** + * Skip iterations and returns iteration state (false if ended, true if still valid). + * + * @param int $count steps number to skip (1 by default) + * + * @return bool + */ + public function skip($count = 1) + { + for ($i = $count; $this->valid() && $i > 0; $i--) { + $this->next(); + } + + return $this->valid(); + } + + /** + * Keep incrementing the current date until a valid date is found or the iteration is ended. + * + * @throws \RuntimeException + * + * @return void + */ + protected function incrementCurrentDateUntilValid() + { + $attempts = 0; + + do { + $this->current->add($this->dateInterval); + + $this->validationResult = null; + + if (++$attempts > static::NEXT_MAX_ATTEMPTS) { + throw new RuntimeException('Could not find next valid date.'); + } + } while ($this->validateCurrentDate() === false); + } + + /** + * Format the date period as ISO 8601. + * + * @return string + */ + public function toIso8601String() + { + $parts = array(); + + if ($this->recurrences !== null) { + $parts[] = 'R'.$this->recurrences; + } + + $parts[] = $this->startDate->toIso8601String(); + + $parts[] = $this->dateInterval->spec(); + + if ($this->endDate !== null) { + $parts[] = $this->endDate->toIso8601String(); + } + + return implode('/', $parts); + } + + /** + * Convert the date period into a string. + * + * @return string + */ + public function toString() + { + $translator = Carbon::getTranslator(); + + $parts = array(); + + $format = !$this->startDate->isStartOfDay() || $this->endDate && !$this->endDate->isStartOfDay() + ? 'Y-m-d H:i:s' + : 'Y-m-d'; + + if ($this->recurrences !== null) { + $parts[] = $translator->transChoice('period_recurrences', $this->recurrences, array(':count' => $this->recurrences)); + } + + $parts[] = $translator->trans('period_interval', array(':interval' => $this->dateInterval->forHumans())); + + $parts[] = $translator->trans('period_start_date', array(':date' => $this->startDate->format($format))); + + if ($this->endDate !== null) { + $parts[] = $translator->trans('period_end_date', array(':date' => $this->endDate->format($format))); + } + + $result = implode(' ', $parts); + + return mb_strtoupper(mb_substr($result, 0, 1)).mb_substr($result, 1); + } + + /** + * Format the date period as ISO 8601. + * + * @return string + */ + public function spec() + { + return $this->toIso8601String(); + } + + /** + * Convert the date period into an array without changing current iteration state. + * + * @return array + */ + public function toArray() + { + $state = array( + $this->key, + $this->current ? $this->current->copy() : null, + $this->validationResult, + ); + + $result = iterator_to_array($this); + + list( + $this->key, + $this->current, + $this->validationResult + ) = $state; + + return $result; + } + + /** + * Count dates in the date period. + * + * @return int + */ + public function count() + { + return count($this->toArray()); + } + + /** + * Return the first date in the date period. + * + * @return Carbon|null + */ + public function first() + { + if ($array = $this->toArray()) { + return $array[0]; + } + } + + /** + * Return the last date in the date period. + * + * @return Carbon|null + */ + public function last() + { + if ($array = $this->toArray()) { + return $array[count($array) - 1]; + } + } + + /** + * Call given macro. + * + * @param string $name + * @param array $parameters + * + * @return mixed + */ + protected function callMacro($name, $parameters) + { + $macro = static::$macros[$name]; + + $reflection = new ReflectionFunction($macro); + + $reflectionParameters = $reflection->getParameters(); + + $expectedCount = count($reflectionParameters); + $actualCount = count($parameters); + + if ($expectedCount > $actualCount && $reflectionParameters[$expectedCount - 1]->name === 'self') { + for ($i = $actualCount; $i < $expectedCount - 1; $i++) { + $parameters[] = $reflectionParameters[$i]->getDefaultValue(); + } + + $parameters[] = $this; + } + + if ($macro instanceof Closure && method_exists($macro, 'bindTo')) { + $macro = $macro->bindTo($this, get_class($this)); + } + + return call_user_func_array($macro, $parameters); + } + + /** + * Convert the date period into a string. + * + * @return string + */ + public function __toString() + { + return $this->toString(); + } + + /** + * Add aliases for setters. + * + * CarbonPeriod::days(3)->hours(5)->invert() + * ->sinceNow()->until('2010-01-10') + * ->filter(...) + * ->count() + * + * Note: We use magic method to let static and instance aliases with the same names. + * + * @param string $method + * @param array $parameters + * + * @return mixed + */ + public function __call($method, $parameters) + { + if (static::hasMacro($method)) { + return $this->callMacro($method, $parameters); + } + + $first = count($parameters) >= 1 ? $parameters[0] : null; + $second = count($parameters) >= 2 ? $parameters[1] : null; + + switch ($method) { + case 'start': + case 'since': + return $this->setStartDate($first, $second); + + case 'sinceNow': + return $this->setStartDate(new Carbon, $first); + + case 'end': + case 'until': + return $this->setEndDate($first, $second); + + case 'untilNow': + return $this->setEndDate(new Carbon, $first); + + case 'dates': + case 'between': + return $this->setDates($first, $second); + + case 'recurrences': + case 'times': + return $this->setRecurrences($first); + + case 'options': + return $this->setOptions($first); + + case 'toggle': + return $this->toggleOptions($first, $second); + + case 'filter': + case 'push': + return $this->addFilter($first, $second); + + case 'prepend': + return $this->prependFilter($first, $second); + + case 'filters': + return $this->setFilters($first ?: array()); + + case 'interval': + case 'each': + case 'every': + case 'step': + case 'stepBy': + return $this->setDateInterval($first); + + case 'invert': + return $this->invertDateInterval(); + + case 'years': + case 'year': + case 'months': + case 'month': + case 'weeks': + case 'week': + case 'days': + case 'dayz': + case 'day': + case 'hours': + case 'hour': + case 'minutes': + case 'minute': + case 'seconds': + case 'second': + return $this->setDateInterval(call_user_func( + // Override default P1D when instantiating via fluent setters. + array($this->isDefaultInterval ? new CarbonInterval('PT0S') : $this->dateInterval, $method), + count($parameters) === 0 ? 1 : $first + )); + } + + throw new BadMethodCallException("Method $method does not exist."); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php new file mode 100644 index 0000000..1b0d473 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Carbon\Exceptions; + +use Exception; +use InvalidArgumentException; + +class InvalidDateException extends InvalidArgumentException +{ + /** + * The invalid field. + * + * @var string + */ + private $field; + + /** + * The invalid value. + * + * @var mixed + */ + private $value; + + /** + * Constructor. + * + * @param string $field + * @param mixed $value + * @param int $code + * @param \Exception|null $previous + */ + public function __construct($field, $value, $code = 0, Exception $previous = null) + { + $this->field = $field; + $this->value = $value; + parent::__construct($field.' : '.$value.' is not a valid value.', $code, $previous); + } + + /** + * Get the invalid field. + * + * @return string + */ + public function getField() + { + return $this->field; + } + + /** + * Get the invalid value. + * + * @return mixed + */ + public function getValue() + { + return $this->value; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/af.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/af.php new file mode 100644 index 0000000..5cf6a8d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/af.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count jaar|:count jare', + 'y' => ':count jaar|:count jare', + 'month' => ':count maand|:count maande', + 'm' => ':count maand|:count maande', + 'week' => ':count week|:count weke', + 'w' => ':count week|:count weke', + 'day' => ':count dag|:count dae', + 'd' => ':count dag|:count dae', + 'hour' => ':count uur|:count ure', + 'h' => ':count uur|:count ure', + 'minute' => ':count minuut|:count minute', + 'min' => ':count minuut|:count minute', + 'second' => ':count sekond|:count sekondes', + 's' => ':count sekond|:count sekondes', + 'ago' => ':time terug', + 'from_now' => ':time van nou af', + 'after' => ':time na', + 'before' => ':time voor', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ar.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ar.php new file mode 100644 index 0000000..de8f6b8 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ar.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => '{0}سنة|{1}سنة|{2}سنتين|[3,10]:count سنوات|[11,Inf]:count سنة', + 'y' => '{0}سنة|{1}سنة|{2}سنتين|[3,10]:count سنوات|[11,Inf]:count سنة', + 'month' => '{0}شهر|{1} شهر|{2}شهرين|[3,10]:count أشهر|[11,Inf]:count شهر', + 'm' => '{0}شهر|{1} شهر|{2}شهرين|[3,10]:count أشهر|[11,Inf]:count شهر', + 'week' => '{0}أسبوع|{1}أسبوع|{2}أسبوعين|[3,10]:count أسابيع|[11,Inf]:count أسبوع', + 'w' => '{0}أسبوع|{1}أسبوع|{2}أسبوعين|[3,10]:count أسابيع|[11,Inf]:count أسبوع', + 'day' => '{0}يوم|{1}يوم|{2}يومين|[3,10]:count أيام|[11,Inf] يوم', + 'd' => '{0}يوم|{1}يوم|{2}يومين|[3,10]:count أيام|[11,Inf] يوم', + 'hour' => '{0}ساعة|{1}ساعة|{2}ساعتين|[3,10]:count ساعات|[11,Inf]:count ساعة', + 'h' => '{0}ساعة|{1}ساعة|{2}ساعتين|[3,10]:count ساعات|[11,Inf]:count ساعة', + 'minute' => '{0}دقيقة|{1}دقيقة|{2}دقيقتين|[3,10]:count دقائق|[11,Inf]:count دقيقة', + 'min' => '{0}دقيقة|{1}دقيقة|{2}دقيقتين|[3,10]:count دقائق|[11,Inf]:count دقيقة', + 'second' => '{0}ثانية|{1}ثانية|{2}ثانيتين|[3,10]:count ثوان|[11,Inf]:count ثانية', + 's' => '{0}ثانية|{1}ثانية|{2}ثانيتين|[3,10]:count ثوان|[11,Inf]:count ثانية', + 'ago' => 'منذ :time', + 'from_now' => ':time من الآن', + 'after' => 'بعد :time', + 'before' => 'قبل :time', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ar_Shakl.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ar_Shakl.php new file mode 100644 index 0000000..846ae02 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ar_Shakl.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => '[0,1] سَنَة|{2} سَنَتَيْن|[3,10]:count سَنَوَات|[11,Inf]:count سَنَة', + 'y' => '[0,1] سَنَة|{2} سَنَتَيْن|[3,10]:count سَنَوَات|[11,Inf]:count سَنَة', + 'month' => '[0,1] شَهْرَ|{2} شَهْرَيْن|[3,10]:count Ø£ÙŽØ´Ù’Ù‡ÙØ±|[11,Inf]:count شَهْرَ', + 'm' => '[0,1] شَهْرَ|{2} شَهْرَيْن|[3,10]:count Ø£ÙŽØ´Ù’Ù‡ÙØ±|[11,Inf]:count شَهْرَ', + 'week' => '[0,1] Ø£ÙØ³Ù’بÙوع|{2} Ø£ÙØ³Ù’بÙوعَيْن|[3,10]:count أَسَابÙيع|[11,Inf]:count Ø£ÙØ³Ù’بÙوع', + 'w' => '[0,1] Ø£ÙØ³Ù’بÙوع|{2} Ø£ÙØ³Ù’بÙوعَيْن|[3,10]:count أَسَابÙيع|[11,Inf]:count Ø£ÙØ³Ù’بÙوع', + 'day' => '[0,1] يَوْم|{2} يَوْمَيْن|[3,10]:count أَيَّام|[11,Inf] يَوْم', + 'd' => '[0,1] يَوْم|{2} يَوْمَيْن|[3,10]:count أَيَّام|[11,Inf] يَوْم', + 'hour' => '[0,1] سَاعَة|{2} سَاعَتَيْن|[3,10]:count سَاعَات|[11,Inf]:count سَاعَة', + 'h' => '[0,1] سَاعَة|{2} سَاعَتَيْن|[3,10]:count سَاعَات|[11,Inf]:count سَاعَة', + 'minute' => '[0,1] دَقÙيقَة|{2} دَقÙيقَتَيْن|[3,10]:count دَقَائÙÙ‚|[11,Inf]:count دَقÙيقَة', + 'min' => '[0,1] دَقÙيقَة|{2} دَقÙيقَتَيْن|[3,10]:count دَقَائÙÙ‚|[11,Inf]:count دَقÙيقَة', + 'second' => '[0,1] ثَانÙÙŠÙŽØ©|{2} ثَانÙيَتَيْن|[3,10]:count ثَوَان|[11,Inf]:count ثَانÙÙŠÙŽØ©', + 's' => '[0,1] ثَانÙÙŠÙŽØ©|{2} ثَانÙيَتَيْن|[3,10]:count ثَوَان|[11,Inf]:count ثَانÙÙŠÙŽØ©', + 'ago' => 'Ù…Ùنْذ٠:time', + 'from_now' => 'Ù…ÙÙ†ÙŽ الْآن :time', + 'after' => 'بَعْدَ :time', + 'before' => 'قَبْلَ :time', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/az.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/az.php new file mode 100644 index 0000000..25f5c4a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/az.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count il', + 'y' => ':count il', + 'month' => ':count ay', + 'm' => ':count ay', + 'week' => ':count hÉ™ftÉ™', + 'w' => ':count hÉ™ftÉ™', + 'day' => ':count gün', + 'd' => ':count gün', + 'hour' => ':count saat', + 'h' => ':count saat', + 'minute' => ':count dÉ™qiqÉ™', + 'min' => ':count dÉ™qiqÉ™', + 'second' => ':count saniyÉ™', + 's' => ':count saniyÉ™', + 'ago' => ':time É™vvÉ™l', + 'from_now' => ':time sonra', + 'after' => ':time sonra', + 'before' => ':time É™vvÉ™l', + 'diff_now' => 'indi', + 'diff_yesterday' => 'dünÉ™n', + 'diff_tomorrow' => 'sabah', + 'diff_before_yesterday' => 'sraÄŸagün', + 'diff_after_tomorrow' => 'birisi gün', + 'period_recurrences' => ':count dÉ™fÉ™dÉ™n bir', + 'period_interval' => 'hÉ™r :interval', + 'period_start_date' => ':date tarixindÉ™n baÅŸlayaraq', + 'period_end_date' => ':date tarixinÉ™dÉ™k', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/bg.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/bg.php new file mode 100644 index 0000000..d9e510b --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/bg.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count година|:count години', + 'y' => ':count година|:count години', + 'month' => ':count меÑец|:count меÑеца', + 'm' => ':count меÑец|:count меÑеца', + 'week' => ':count Ñедмица|:count Ñедмици', + 'w' => ':count Ñедмица|:count Ñедмици', + 'day' => ':count ден|:count дни', + 'd' => ':count ден|:count дни', + 'hour' => ':count чаÑ|:count чаÑа', + 'h' => ':count чаÑ|:count чаÑа', + 'minute' => ':count минута|:count минути', + 'min' => ':count минута|:count минути', + 'second' => ':count Ñекунда|:count Ñекунди', + 's' => ':count Ñекунда|:count Ñекунди', + 'ago' => 'преди :time', + 'from_now' => ':time от Ñега', + 'after' => 'Ñлед :time', + 'before' => 'преди :time', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/bn.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/bn.php new file mode 100644 index 0000000..5817599 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/bn.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => 'à§§ বছর|:count বছর', + 'y' => 'à§§ বছর|:count বছর', + 'month' => 'à§§ মাস|:count মাস', + 'm' => 'à§§ মাস|:count মাস', + 'week' => 'à§§ সপà§à¦¤à¦¾à¦¹|:count সপà§à¦¤à¦¾à¦¹', + 'w' => 'à§§ সপà§à¦¤à¦¾à¦¹|:count সপà§à¦¤à¦¾à¦¹', + 'day' => 'à§§ দিন|:count দিন', + 'd' => 'à§§ দিন|:count দিন', + 'hour' => 'à§§ ঘনà§à¦Ÿà¦¾|:count ঘনà§à¦Ÿà¦¾', + 'h' => 'à§§ ঘনà§à¦Ÿà¦¾|:count ঘনà§à¦Ÿà¦¾', + 'minute' => 'à§§ মিনিট|:count মিনিট', + 'min' => 'à§§ মিনিট|:count মিনিট', + 'second' => 'à§§ সেকেনà§à¦¡|:count সেকেনà§à¦¡', + 's' => 'à§§ সেকেনà§à¦¡|:count সেকেনà§à¦¡', + 'ago' => ':time পূরà§à¦¬à§‡', + 'from_now' => 'à¦à¦–ন থেকে :time', + 'after' => ':time পরে', + 'before' => ':time আগে', + 'diff_now' => 'à¦à¦–ন', + 'diff_yesterday' => 'গতকাল', + 'diff_tomorrow' => 'আগামীকাল', + 'period_recurrences' => ':count বার|:count বার', + 'period_interval' => 'পà§à¦°à¦¤à¦¿ :interval', + 'period_start_date' => ':date থেকে', + 'period_end_date' => ':date পরà§à¦¯à¦¨à§à¦¤', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/bs_BA.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/bs_BA.php new file mode 100644 index 0000000..7a9b05a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/bs_BA.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count godina|:count godine|:count godina', + 'y' => ':count godina|:count godine|:count godina', + 'month' => ':count mjesec|:count mjeseca|:count mjeseci', + 'm' => ':count mjesec|:count mjeseca|:count mjeseci', + 'week' => ':count nedjelja|:count nedjelje|:count nedjelja', + 'w' => ':count nedjelja|:count nedjelje|:count nedjelja', + 'day' => ':count dan|:count dana|:count dana', + 'd' => ':count dan|:count dana|:count dana', + 'hour' => ':count sat|:count sata|:count sati', + 'h' => ':count sat|:count sata|:count sati', + 'minute' => ':count minut|:count minuta|:count minuta', + 'min' => ':count minut|:count minuta|:count minuta', + 'second' => ':count sekund|:count sekunda|:count sekundi', + 's' => ':count sekund|:count sekunda|:count sekundi', + 'ago' => 'prije :time', + 'from_now' => 'za :time', + 'after' => 'nakon :time', + 'before' => ':time ranije', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ca.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ca.php new file mode 100644 index 0000000..c854b5a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ca.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count any|:count anys', + 'y' => ':count any|:count anys', + 'month' => ':count mes|:count mesos', + 'm' => ':count mes|:count mesos', + 'week' => ':count setmana|:count setmanes', + 'w' => ':count setmana|:count setmanes', + 'day' => ':count dia|:count dies', + 'd' => ':count dia|:count dies', + 'hour' => ':count hora|:count hores', + 'h' => ':count hora|:count hores', + 'minute' => ':count minut|:count minuts', + 'min' => ':count minut|:count minuts', + 'second' => ':count segon|:count segons', + 's' => ':count segon|:count segons', + 'ago' => 'fa :time', + 'from_now' => 'd\'aquí :time', + 'after' => ':time després', + 'before' => ':time abans', + 'diff_now' => 'ara mateix', + 'diff_yesterday' => 'ahir', + 'diff_tomorrow' => 'demà', + 'diff_before_yesterday' => "abans d'ahir", + 'diff_after_tomorrow' => 'demà passat', + 'period_recurrences' => ':count cop|:count cops', + 'period_interval' => 'cada :interval', + 'period_start_date' => 'de :date', + 'period_end_date' => 'fins a :date', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/cs.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/cs.php new file mode 100644 index 0000000..a447ce2 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/cs.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count rok|:count roky|:count let', + 'y' => ':count rok|:count roky|:count let', + 'month' => ':count mÄ›síc|:count mÄ›síce|:count mÄ›síců', + 'm' => ':count mÄ›síc|:count mÄ›síce|:count mÄ›síců', + 'week' => ':count týden|:count týdny|:count týdnů', + 'w' => ':count týden|:count týdny|:count týdnů', + 'day' => ':count den|:count dny|:count dní', + 'd' => ':count den|:count dny|:count dní', + 'hour' => ':count hodinu|:count hodiny|:count hodin', + 'h' => ':count hodinu|:count hodiny|:count hodin', + 'minute' => ':count minutu|:count minuty|:count minut', + 'min' => ':count minutu|:count minuty|:count minut', + 'second' => ':count sekundu|:count sekundy|:count sekund', + 's' => ':count sekundu|:count sekundy|:count sekund', + 'ago' => ':time nazpÄ›t', + 'from_now' => 'za :time', + 'after' => ':time pozdÄ›ji', + 'before' => ':time pÅ™edtím', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/cy.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/cy.php new file mode 100644 index 0000000..c93750e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/cy.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +return array( + 'year' => '1 flwyddyn|:count blynedd', + 'y' => ':countbl', + 'month' => '1 mis|:count fis', + 'm' => ':countmi', + 'week' => ':count wythnos', + 'w' => ':countw', + 'day' => ':count diwrnod', + 'd' => ':countd', + 'hour' => ':count awr', + 'h' => ':counth', + 'minute' => ':count munud', + 'min' => ':countm', + 'second' => ':count eiliad', + 's' => ':counts', + 'ago' => ':time yn ôl', + 'from_now' => ':time o hyn ymlaen', + 'after' => ':time ar ôl', + 'before' => ':time o\'r blaen', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/da.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/da.php new file mode 100644 index 0000000..86507b0 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/da.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count Ã¥r|:count Ã¥r', + 'y' => ':count Ã¥r|:count Ã¥r', + 'month' => ':count mÃ¥ned|:count mÃ¥neder', + 'm' => ':count mÃ¥ned|:count mÃ¥neder', + 'week' => ':count uge|:count uger', + 'w' => ':count uge|:count uger', + 'day' => ':count dag|:count dage', + 'd' => ':count dag|:count dage', + 'hour' => ':count time|:count timer', + 'h' => ':count time|:count timer', + 'minute' => ':count minut|:count minutter', + 'min' => ':count minut|:count minutter', + 'second' => ':count sekund|:count sekunder', + 's' => ':count sekund|:count sekunder', + 'ago' => ':time siden', + 'from_now' => 'om :time', + 'after' => ':time efter', + 'before' => ':time før', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/de.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/de.php new file mode 100644 index 0000000..5ea2a03 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/de.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count Jahr|:count Jahre', + 'y' => ':countJ|:countJ', + 'month' => ':count Monat|:count Monate', + 'm' => ':countMon|:countMon', + 'week' => ':count Woche|:count Wochen', + 'w' => ':countWo|:countWo', + 'day' => ':count Tag|:count Tage', + 'd' => ':countTg|:countTg', + 'hour' => ':count Stunde|:count Stunden', + 'h' => ':countStd|:countStd', + 'minute' => ':count Minute|:count Minuten', + 'min' => ':countMin|:countMin', + 'second' => ':count Sekunde|:count Sekunden', + 's' => ':countSek|:countSek', + 'ago' => 'vor :time', + 'from_now' => 'in :time', + 'after' => ':time später', + 'before' => ':time zuvor', + + 'year_from_now' => ':count Jahr|:count Jahren', + 'month_from_now' => ':count Monat|:count Monaten', + 'week_from_now' => ':count Woche|:count Wochen', + 'day_from_now' => ':count Tag|:count Tagen', + 'year_ago' => ':count Jahr|:count Jahren', + 'month_ago' => ':count Monat|:count Monaten', + 'week_ago' => ':count Woche|:count Wochen', + 'day_ago' => ':count Tag|:count Tagen', + + 'diff_now' => 'Gerade eben', + 'diff_yesterday' => 'Gestern', + 'diff_tomorrow' => 'Heute', + 'diff_before_yesterday' => 'Vorgestern', + 'diff_after_tomorrow' => 'Übermorgen', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/dv_MV.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/dv_MV.php new file mode 100644 index 0000000..e3c50b3 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/dv_MV.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => '{0}Þ‡Þ¦Þ€Þ¦ÞƒÞ¬Þ‡Þ°|[1,Inf]:count Þ‡Þ¦Þ€Þ¦ÞƒÞª', + 'y' => '{0}Þ‡Þ¦Þ€Þ¦ÞƒÞ¬Þ‡Þ°|[1,Inf]:count Þ‡Þ¦Þ€Þ¦ÞƒÞª', + 'month' => '{0}Þ‰Þ¦Þ‡Þ°ÞÞ¦ÞƒÞ¬Þ‡Þ°|[1,Inf]:count Þ‰Þ¦ÞÞ°', + 'm' => '{0}Þ‰Þ¦Þ‡Þ°ÞÞ¦ÞƒÞ¬Þ‡Þ°|[1,Inf]:count Þ‰Þ¦ÞÞ°', + 'week' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ', + 'w' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ', + 'day' => '{0}Þ‹ÞªÞˆÞ¦ÞÞ°|[1,Inf]:count Þ‹ÞªÞˆÞ¦ÞÞ°', + 'd' => '{0}Þ‹ÞªÞˆÞ¦ÞÞ°|[1,Inf]:count Þ‹ÞªÞˆÞ¦ÞÞ°', + 'hour' => '{0}ÞŽÞ¦Þ‘Þ¨Þ‡Þ¨ÞƒÞ¬Þ‡Þ°|[1,Inf]:count ÞŽÞ¦Þ‘Þ¨', + 'h' => '{0}ÞŽÞ¦Þ‘Þ¨Þ‡Þ¨ÞƒÞ¬Þ‡Þ°|[1,Inf]:count ÞŽÞ¦Þ‘Þ¨', + 'minute' => '{0}Þ‰Þ¨Þ‚Þ¬Þ“Þ¬Þ‡Þ°|[1,Inf]:count Þ‰Þ¨Þ‚Þ¬Þ“Þ°', + 'min' => '{0}Þ‰Þ¨Þ‚Þ¬Þ“Þ¬Þ‡Þ°|[1,Inf]:count Þ‰Þ¨Þ‚Þ¬Þ“Þ°', + 'second' => '{0}Þިކުންތެއް|[1,Inf]:count Þިކުންތު', + 's' => '{0}Þިކުންތެއް|[1,Inf]:count Þިކުންތު', + 'ago' => ':time Þ†ÞªÞƒÞ¨Þ‚Þ°', + 'from_now' => ':time ÞŠÞ¦Þ€ÞªÞ‚Þ°', + 'after' => ':time ÞŠÞ¦Þ€ÞªÞ‚Þ°', + 'before' => ':time Þ†ÞªÞƒÞ¨', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/el.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/el.php new file mode 100644 index 0000000..16b3f44 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/el.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count χÏόνος|:count χÏόνια', + 'y' => ':count χÏόνος|:count χÏόνια', + 'month' => ':count μήνας|:count μήνες', + 'm' => ':count μήνας|:count μήνες', + 'week' => ':count εβδομάδα|:count εβδομάδες', + 'w' => ':count εβδομάδα|:count εβδομάδες', + 'day' => ':count μέÏα|:count μέÏες', + 'd' => ':count μέÏα|:count μέÏες', + 'hour' => ':count ÏŽÏα|:count ÏŽÏες', + 'h' => ':count ÏŽÏα|:count ÏŽÏες', + 'minute' => ':count λεπτό|:count λεπτά', + 'min' => ':count λεπτό|:count λεπτά', + 'second' => ':count δευτεÏόλεπτο|:count δευτεÏόλεπτα', + 's' => ':count δευτεÏόλεπτο|:count δευτεÏόλεπτα', + 'ago' => 'Ï€Ïιν από :time', + 'from_now' => 'σε :time από τώÏα', + 'after' => ':time μετά', + 'before' => ':time Ï€Ïιν', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/en.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/en.php new file mode 100644 index 0000000..a15c131 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/en.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count year|:count years', + 'y' => ':countyr|:countyrs', + 'month' => ':count month|:count months', + 'm' => ':countmo|:countmos', + 'week' => ':count week|:count weeks', + 'w' => ':countw|:countw', + 'day' => ':count day|:count days', + 'd' => ':countd|:countd', + 'hour' => ':count hour|:count hours', + 'h' => ':counth|:counth', + 'minute' => ':count minute|:count minutes', + 'min' => ':countm|:countm', + 'second' => ':count second|:count seconds', + 's' => ':counts|:counts', + 'ago' => ':time ago', + 'from_now' => ':time from now', + 'after' => ':time after', + 'before' => ':time before', + 'diff_now' => 'just now', + 'diff_yesterday' => 'yesterday', + 'diff_tomorrow' => 'tomorrow', + 'diff_before_yesterday' => 'before yesterday', + 'diff_after_tomorrow' => 'after tomorrow', + 'period_recurrences' => 'once|:count times', + 'period_interval' => 'every :interval', + 'period_start_date' => 'from :date', + 'period_end_date' => 'to :date', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/eo.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/eo.php new file mode 100644 index 0000000..c5b90b3 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/eo.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count jaro|:count jaroj', + 'y' => ':count jaro|:count jaroj', + 'month' => ':count monato|:count monatoj', + 'm' => ':count monato|:count monatoj', + 'week' => ':count semajno|:count semajnoj', + 'w' => ':count semajno|:count semajnoj', + 'day' => ':count tago|:count tagoj', + 'd' => ':count tago|:count tagoj', + 'hour' => ':count horo|:count horoj', + 'h' => ':count horo|:count horoj', + 'minute' => ':count minuto|:count minutoj', + 'min' => ':count minuto|:count minutoj', + 'second' => ':count sekundo|:count sekundoj', + 's' => ':count sekundo|:count sekundoj', + 'ago' => 'antaÅ­ :time', + 'from_now' => 'je :time', + 'after' => ':time poste', + 'before' => ':time antaÅ­e', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/es.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/es.php new file mode 100644 index 0000000..567a280 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/es.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count año|:count años', + 'y' => ':count año|:count años', + 'month' => ':count mes|:count meses', + 'm' => ':count mes|:count meses', + 'week' => ':count semana|:count semanas', + 'w' => ':count semana|:count semanas', + 'day' => ':count día|:count días', + 'd' => ':count día|:count días', + 'hour' => ':count hora|:count horas', + 'h' => ':count hora|:count horas', + 'minute' => ':count minuto|:count minutos', + 'min' => ':count minuto|:count minutos', + 'second' => ':count segundo|:count segundos', + 's' => ':count segundo|:count segundos', + 'ago' => 'hace :time', + 'from_now' => 'dentro de :time', + 'after' => ':time después', + 'before' => ':time antes', + 'diff_now' => 'ahora mismo', + 'diff_yesterday' => 'ayer', + 'diff_tomorrow' => 'mañana', + 'diff_before_yesterday' => 'antier', + 'diff_after_tomorrow' => 'pasado mañana', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/et.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/et.php new file mode 100644 index 0000000..2d9291e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/et.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count aasta|:count aastat', + 'y' => ':count aasta|:count aastat', + 'month' => ':count kuu|:count kuud', + 'm' => ':count kuu|:count kuud', + 'week' => ':count nädal|:count nädalat', + 'w' => ':count nädal|:count nädalat', + 'day' => ':count päev|:count päeva', + 'd' => ':count päev|:count päeva', + 'hour' => ':count tund|:count tundi', + 'h' => ':count tund|:count tundi', + 'minute' => ':count minut|:count minutit', + 'min' => ':count minut|:count minutit', + 'second' => ':count sekund|:count sekundit', + 's' => ':count sekund|:count sekundit', + 'ago' => ':time tagasi', + 'from_now' => ':time pärast', + 'after' => ':time pärast', + 'before' => ':time enne', + 'year_from_now' => ':count aasta', + 'month_from_now' => ':count kuu', + 'week_from_now' => ':count nädala', + 'day_from_now' => ':count päeva', + 'hour_from_now' => ':count tunni', + 'minute_from_now' => ':count minuti', + 'second_from_now' => ':count sekundi', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/eu.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/eu.php new file mode 100644 index 0000000..1cb6b7c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/eu.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => 'Urte 1|:count urte', + 'y' => 'Urte 1|:count urte', + 'month' => 'Hile 1|:count hile', + 'm' => 'Hile 1|:count hile', + 'week' => 'Aste 1|:count aste', + 'w' => 'Aste 1|:count aste', + 'day' => 'Egun 1|:count egun', + 'd' => 'Egun 1|:count egun', + 'hour' => 'Ordu 1|:count ordu', + 'h' => 'Ordu 1|:count ordu', + 'minute' => 'Minutu 1|:count minutu', + 'min' => 'Minutu 1|:count minutu', + 'second' => 'Segundu 1|:count segundu', + 's' => 'Segundu 1|:count segundu', + 'ago' => 'Orain dela :time', + 'from_now' => ':time barru', + 'after' => ':time geroago', + 'before' => ':time lehenago', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fa.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fa.php new file mode 100644 index 0000000..31bec88 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fa.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count سال', + 'y' => ':count سال', + 'month' => ':count ماه', + 'm' => ':count ماه', + 'week' => ':count Ù‡ÙØªÙ‡', + 'w' => ':count Ù‡ÙØªÙ‡', + 'day' => ':count روز', + 'd' => ':count روز', + 'hour' => ':count ساعت', + 'h' => ':count ساعت', + 'minute' => ':count دقیقه', + 'min' => ':count دقیقه', + 'second' => ':count ثانیه', + 's' => ':count ثانیه', + 'ago' => ':time پیش', + 'from_now' => ':time بعد', + 'after' => ':time پس از', + 'before' => ':time پیش از', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fi.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fi.php new file mode 100644 index 0000000..4818804 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fi.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count vuosi|:count vuotta', + 'y' => ':count vuosi|:count vuotta', + 'month' => ':count kuukausi|:count kuukautta', + 'm' => ':count kuukausi|:count kuukautta', + 'week' => ':count viikko|:count viikkoa', + 'w' => ':count viikko|:count viikkoa', + 'day' => ':count päivä|:count päivää', + 'd' => ':count päivä|:count päivää', + 'hour' => ':count tunti|:count tuntia', + 'h' => ':count tunti|:count tuntia', + 'minute' => ':count minuutti|:count minuuttia', + 'min' => ':count minuutti|:count minuuttia', + 'second' => ':count sekunti|:count sekuntia', + 's' => ':count sekunti|:count sekuntia', + 'ago' => ':time sitten', + 'from_now' => ':time tästä hetkestä', + 'after' => ':time sen jälkeen', + 'before' => ':time ennen', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fo.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fo.php new file mode 100644 index 0000000..d91104b --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fo.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count ár|:count ár', + 'y' => ':count ár|:count ár', + 'month' => ':count mánaður|:count mánaðir', + 'm' => ':count mánaður|:count mánaðir', + 'week' => ':count vika|:count vikur', + 'w' => ':count vika|:count vikur', + 'day' => ':count dag|:count dagar', + 'd' => ':count dag|:count dagar', + 'hour' => ':count tími|:count tímar', + 'h' => ':count tími|:count tímar', + 'minute' => ':count minutt|:count minuttir', + 'min' => ':count minutt|:count minuttir', + 'second' => ':count sekund|:count sekundir', + 's' => ':count sekund|:count sekundir', + 'ago' => ':time síðan', + 'from_now' => 'um :time', + 'after' => ':time aftaná', + 'before' => ':time áðrenn', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fr.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fr.php new file mode 100644 index 0000000..0b20cdd --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/fr.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count an|:count ans', + 'y' => ':count an|:count ans', + 'month' => ':count mois', + 'm' => ':count mois', + 'week' => ':count semaine|:count semaines', + 'w' => ':count sem.', + 'day' => ':count jour|:count jours', + 'd' => ':count j.', + 'hour' => ':count heure|:count heures', + 'h' => ':count h.', + 'minute' => ':count minute|:count minutes', + 'min' => ':count min.', + 'second' => ':count seconde|:count secondes', + 's' => ':count sec.', + 'ago' => 'il y a :time', + 'from_now' => 'dans :time', + 'after' => ':time après', + 'before' => ':time avant', + 'diff_now' => "à l'instant", + 'diff_yesterday' => 'hier', + 'diff_tomorrow' => 'demain', + 'diff_before_yesterday' => 'avant-hier', + 'diff_after_tomorrow' => 'après-demain', + 'period_recurrences' => ':count fois', + 'period_interval' => 'tous les :interval', + 'period_start_date' => 'de :date', + 'period_end_date' => 'à :date', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/gl.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/gl.php new file mode 100644 index 0000000..cd22a31 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/gl.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count ano|:count anos', + 'month' => ':count mes|:count meses', + 'week' => ':count semana|:count semanas', + 'day' => ':count día|:count días', + 'hour' => ':count hora|:count horas', + 'minute' => ':count minuto|:count minutos', + 'second' => ':count segundo|:count segundos', + 'ago' => 'fai :time', + 'from_now' => 'dentro de :time', + 'after' => ':time despois', + 'before' => ':time antes', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/gu.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/gu.php new file mode 100644 index 0000000..7759dfc --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/gu.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count વરà«àª·|:count વરà«àª·à«‹', + 'y' => ':countવરà«àª·|:countવરà«àª·à«‹', + 'month' => ':count મહિનો|:count મહિના', + 'm' => ':countમહિનો|:countમહિના', + 'week' => ':count અઠવાડિયà«àª‚|:count અઠવાડિયા', + 'w' => ':countઅઠ.|:countઅઠ.', + 'day' => ':count દિવસ|:count દિવસો', + 'd' => ':countદિ.|:countદિ.', + 'hour' => ':count કલાક|:count કલાકો', + 'h' => ':countક.|:countક.', + 'minute' => ':count મિનિટ|:count મિનિટ', + 'min' => ':countમિ.|:countમિ.', + 'second' => ':count સેકેનà«àª¡|:count સેકેનà«àª¡', + 's' => ':countસે.|:countસે.', + 'ago' => ':time પહેલા', + 'from_now' => ':time અતà«àª¯àª¾àª°àª¥à«€', + 'after' => ':time પછી', + 'before' => ':time પહેલા', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/he.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/he.php new file mode 100644 index 0000000..2d4f4f8 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/he.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => 'שנה|{2}שנתיי×|:count שני×', + 'y' => 'שנה|{2}שנתיי×|:count שני×', + 'month' => 'חודש|{2}חודשיי×|:count חודשי×', + 'm' => 'חודש|{2}חודשיי×|:count חודשי×', + 'week' => 'שבוע|{2}שבועיי×|:count שבועות', + 'w' => 'שבוע|{2}שבועיי×|:count שבועות', + 'day' => 'יו×|{2}יומיי×|:count ימי×', + 'd' => 'יו×|{2}יומיי×|:count ימי×', + 'hour' => 'שעה|{2}שעתיי×|:count שעות', + 'h' => 'שעה|{2}שעתיי×|:count שעות', + 'minute' => 'דקה|{2}דקותיי×|:count דקות', + 'min' => 'דקה|{2}דקותיי×|:count דקות', + 'second' => 'שניה|:count שניות', + 's' => 'שניה|:count שניות', + 'ago' => 'לפני :time', + 'from_now' => 'בעוד :time', + 'after' => '×חרי :time', + 'before' => 'לפני :time', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hi.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hi.php new file mode 100644 index 0000000..6c670ee --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hi.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => '1 वरà¥à¤·|:count वरà¥à¤·à¥‹à¤‚', + 'y' => '1 वरà¥à¤·|:count वरà¥à¤·à¥‹à¤‚', + 'month' => '1 माह|:count महीने', + 'm' => '1 माह|:count महीने', + 'week' => '1 सपà¥à¤¤à¤¾à¤¹|:count सपà¥à¤¤à¤¾à¤¹', + 'w' => '1 सपà¥à¤¤à¤¾à¤¹|:count सपà¥à¤¤à¤¾à¤¹', + 'day' => '1 दिन|:count दिनों', + 'd' => '1 दिन|:count दिनों', + 'hour' => '1 घंटा|:count घंटे', + 'h' => '1 घंटा|:count घंटे', + 'minute' => '1 मिनट|:count मिनटों', + 'min' => '1 मिनट|:count मिनटों', + 'second' => '1 सेकंड|:count सेकंड', + 's' => '1 सेकंड|:count सेकंड', + 'ago' => ':time पूरà¥à¤µ', + 'from_now' => ':time से', + 'after' => ':time के बाद', + 'before' => ':time के पहले', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hr.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hr.php new file mode 100644 index 0000000..1a339de --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hr.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count godinu|:count godine|:count godina', + 'y' => ':count godinu|:count godine|:count godina', + 'month' => ':count mjesec|:count mjeseca|:count mjeseci', + 'm' => ':count mjesec|:count mjeseca|:count mjeseci', + 'week' => ':count tjedan|:count tjedna|:count tjedana', + 'w' => ':count tjedan|:count tjedna|:count tjedana', + 'day' => ':count dan|:count dana|:count dana', + 'd' => ':count dan|:count dana|:count dana', + 'hour' => ':count sat|:count sata|:count sati', + 'h' => ':count sat|:count sata|:count sati', + 'minute' => ':count minutu|:count minute |:count minuta', + 'min' => ':count minutu|:count minute |:count minuta', + 'second' => ':count sekundu|:count sekunde|:count sekundi', + 's' => ':count sekundu|:count sekunde|:count sekundi', + 'ago' => 'prije :time', + 'from_now' => 'za :time', + 'after' => 'za :time', + 'before' => 'prije :time', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hu.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hu.php new file mode 100644 index 0000000..45daf41 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hu.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count év', + 'y' => ':count év', + 'month' => ':count hónap', + 'm' => ':count hónap', + 'week' => ':count hét', + 'w' => ':count hét', + 'day' => ':count nap', + 'd' => ':count nap', + 'hour' => ':count óra', + 'h' => ':count óra', + 'minute' => ':count perc', + 'min' => ':count perc', + 'second' => ':count másodperc', + 's' => ':count másodperc', + 'ago' => ':time', + 'from_now' => ':time múlva', + 'after' => ':time késÅ‘bb', + 'before' => ':time korábban', + 'year_ago' => ':count éve', + 'month_ago' => ':count hónapja', + 'week_ago' => ':count hete', + 'day_ago' => ':count napja', + 'hour_ago' => ':count órája', + 'minute_ago' => ':count perce', + 'second_ago' => ':count másodperce', + 'year_after' => ':count évvel', + 'month_after' => ':count hónappal', + 'week_after' => ':count héttel', + 'day_after' => ':count nappal', + 'hour_after' => ':count órával', + 'minute_after' => ':count perccel', + 'second_after' => ':count másodperccel', + 'year_before' => ':count évvel', + 'month_before' => ':count hónappal', + 'week_before' => ':count héttel', + 'day_before' => ':count nappal', + 'hour_before' => ':count órával', + 'minute_before' => ':count perccel', + 'second_before' => ':count másodperccel', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hy.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hy.php new file mode 100644 index 0000000..d2665f2 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/hy.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count Õ¿Õ¡Ö€Õ«', + 'y' => ':countÕ¿', + 'month' => ':count Õ¡Õ´Õ«Õ½', + 'm' => ':countÕ¡Õ´', + 'week' => ':count Õ·Õ¡Õ¢Õ¡Õ©', + 'w' => ':countÕ·', + 'day' => ':count Ö…Ö€', + 'd' => ':countÖ…Ö€', + 'hour' => ':count ÕªÕ¡Õ´', + 'h' => ':countÕª', + 'minute' => ':count Ö€Õ¸ÕºÕ¥', + 'min' => ':countÖ€', + 'second' => ':count Õ¾Õ¡Ö€Õ¯ÕµÕ¡Õ¶', + 's' => ':countÕ¾Ö€Õ¯', + 'ago' => ':time Õ¡Õ¼Õ¡Õ»', + 'from_now' => ':time Õ¶Õ¥Ö€Õ¯Õ¡ ÕºÕ¡Õ°Õ«Ö', + 'after' => ':time Õ°Õ¥Õ¿Õ¸', + 'before' => ':time Õ¡Õ¼Õ¡Õ»', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/id.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/id.php new file mode 100644 index 0000000..7f7114f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/id.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count tahun', + 'y' => ':count tahun', + 'month' => ':count bulan', + 'm' => ':count bulan', + 'week' => ':count minggu', + 'w' => ':count minggu', + 'day' => ':count hari', + 'd' => ':count hari', + 'hour' => ':count jam', + 'h' => ':count jam', + 'minute' => ':count menit', + 'min' => ':count menit', + 'second' => ':count detik', + 's' => ':count detik', + 'ago' => ':time yang lalu', + 'from_now' => ':time dari sekarang', + 'after' => ':time setelah', + 'before' => ':time sebelum', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/is.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/is.php new file mode 100644 index 0000000..94c76a7 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/is.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => '1 ár|:count ár', + 'y' => '1 ár|:count ár', + 'month' => '1 mánuður|:count mánuðir', + 'm' => '1 mánuður|:count mánuðir', + 'week' => '1 vika|:count vikur', + 'w' => '1 vika|:count vikur', + 'day' => '1 dagur|:count dagar', + 'd' => '1 dagur|:count dagar', + 'hour' => '1 klukkutími|:count klukkutímar', + 'h' => '1 klukkutími|:count klukkutímar', + 'minute' => '1 mínúta|:count mínútur', + 'min' => '1 mínúta|:count mínútur', + 'second' => '1 sekúnda|:count sekúndur', + 's' => '1 sekúnda|:count sekúndur', + 'ago' => ':time síðan', + 'from_now' => ':time síðan', + 'after' => ':time eftir', + 'before' => ':time fyrir', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/it.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/it.php new file mode 100644 index 0000000..70bc6d7 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/it.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count anno|:count anni', + 'y' => ':count anno|:count anni', + 'month' => ':count mese|:count mesi', + 'm' => ':count mese|:count mesi', + 'week' => ':count settimana|:count settimane', + 'w' => ':count settimana|:count settimane', + 'day' => ':count giorno|:count giorni', + 'd' => ':count giorno|:count giorni', + 'hour' => ':count ora|:count ore', + 'h' => ':count ora|:count ore', + 'minute' => ':count minuto|:count minuti', + 'min' => ':count minuto|:count minuti', + 'second' => ':count secondo|:count secondi', + 's' => ':count secondo|:count secondi', + 'ago' => ':time fa', + 'from_now' => 'tra :time', + 'after' => ':time dopo', + 'before' => ':time prima', + 'diff_now' => 'proprio ora', + 'diff_yesterday' => 'ieri', + 'diff_tomorrow' => 'domani', + 'diff_before_yesterday' => "l'altro ieri", + 'diff_after_tomorrow' => 'dopodomani', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ja.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ja.php new file mode 100644 index 0000000..7119547 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ja.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':countå¹´', + 'y' => ':countå¹´', + 'month' => ':countヶ月', + 'm' => ':countヶ月', + 'week' => ':count週間', + 'w' => ':count週間', + 'day' => ':countæ—¥', + 'd' => ':countæ—¥', + 'hour' => ':count時間', + 'h' => ':count時間', + 'minute' => ':count分', + 'min' => ':count分', + 'second' => ':countç§’', + 's' => ':countç§’', + 'ago' => ':timeå‰', + 'from_now' => '今ã‹ã‚‰:time', + 'after' => ':time後', + 'before' => ':timeå‰', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ka.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ka.php new file mode 100644 index 0000000..a8dde7e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ka.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count წლის', + 'y' => ':count წლის', + 'month' => ':count თვის', + 'm' => ':count თვის', + 'week' => ':count კვირის', + 'w' => ':count კვირის', + 'day' => ':count დღის', + 'd' => ':count დღის', + 'hour' => ':count სáƒáƒáƒ—ის', + 'h' => ':count სáƒáƒáƒ—ის', + 'minute' => ':count წუთის', + 'min' => ':count წუთის', + 'second' => ':count წáƒáƒ›áƒ˜áƒ¡', + 's' => ':count წáƒáƒ›áƒ˜áƒ¡', + 'ago' => ':time უკáƒáƒœ', + 'from_now' => ':time შემდეგ', + 'after' => ':time შემდეგ', + 'before' => ':time უკáƒáƒœ', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/kk.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/kk.php new file mode 100644 index 0000000..8d113af --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/kk.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +return array( + 'year' => ':count жыл', + 'y' => ':count жыл', + 'month' => ':count ай', + 'm' => ':count ай', + 'week' => ':count апта', + 'w' => ':count апта', + 'day' => ':count күн', + 'd' => ':count күн', + 'hour' => ':count Ñағат', + 'h' => ':count Ñағат', + 'minute' => ':count минут', + 'min' => ':count минут', + 'second' => ':count Ñекунд', + 's' => ':count Ñекунд', + 'ago' => ':time бұрын', + 'from_now' => ':time кейін', + 'after' => ':time кейін', + 'before' => ':time бұрын', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/km.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/km.php new file mode 100644 index 0000000..a104e06 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/km.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count ឆ្នាំ', + 'y' => ':count ឆ្នាំ', + 'month' => ':count ážáŸ‚', + 'm' => ':count ážáŸ‚', + 'week' => ':count សប្ដាហáŸ', + 'w' => ':count សប្ដាហáŸ', + 'day' => ':count ážáŸ’ងៃ', + 'd' => ':count ážáŸ’ងៃ', + 'hour' => ':count ម៉ោង', + 'h' => ':count ម៉ោង', + 'minute' => ':count នាទី', + 'min' => ':count នាទី', + 'second' => ':count វិនាទី', + 's' => ':count វិនាទី', + 'ago' => ':timeមុន', + 'from_now' => ':timeពី​ឥឡូវ', + 'after' => 'នៅ​ក្រោយ :time', + 'before' => 'នៅ​មុន :time', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ko.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ko.php new file mode 100644 index 0000000..0209164 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ko.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count ë…„', + 'y' => ':count ë…„', + 'month' => ':count 개월', + 'm' => ':count 개월', + 'week' => ':count 주ì¼', + 'w' => ':count 주ì¼', + 'day' => ':count ì¼', + 'd' => ':count ì¼', + 'hour' => ':count 시간', + 'h' => ':count 시간', + 'minute' => ':count ë¶„', + 'min' => ':count ë¶„', + 'second' => ':count ì´ˆ', + 's' => ':count ì´ˆ', + 'ago' => ':time ì „', + 'from_now' => ':time 후', + 'after' => ':time ì´í›„', + 'before' => ':time ì´ì „', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/lt.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/lt.php new file mode 100644 index 0000000..3f2fd1e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/lt.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count metus|:count metus|:count metų', + 'y' => ':count metus|:count metus|:count metų', + 'month' => ':count mÄ—nesį|:count mÄ—nesius|:count mÄ—nesių', + 'm' => ':count mÄ—nesį|:count mÄ—nesius|:count mÄ—nesių', + 'week' => ':count savaitÄ™|:count savaites|:count savaiÄių', + 'w' => ':count savaitÄ™|:count savaites|:count savaiÄių', + 'day' => ':count dienÄ…|:count dienas|:count dienų', + 'd' => ':count dienÄ…|:count dienas|:count dienų', + 'hour' => ':count valandÄ…|:count valandas|:count valandų', + 'h' => ':count valandÄ…|:count valandas|:count valandų', + 'minute' => ':count minutÄ™|:count minutes|:count minuÄių', + 'min' => ':count minutÄ™|:count minutes|:count minuÄių', + 'second' => ':count sekundÄ™|:count sekundes|:count sekundžių', + 's' => ':count sekundÄ™|:count sekundes|:count sekundžių', + 'second_from_now' => ':count sekundÄ—s|:count sekundžių|:count sekundžių', + 'minute_from_now' => ':count minutÄ—s|:count minuÄių|:count minuÄių', + 'hour_from_now' => ':count valandos|:count valandų|:count valandų', + 'day_from_now' => ':count dienos|:count dienų|:count dienų', + 'week_from_now' => ':count savaitÄ—s|:count savaiÄių|:count savaiÄių', + 'month_from_now' => ':count mÄ—nesio|:count mÄ—nesių|:count mÄ—nesių', + 'year_from_now' => ':count metų', + 'ago' => 'prieÅ¡ :time', + 'from_now' => 'už :time', + 'after' => 'po :time', + 'before' => ':time nuo dabar', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/lv.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/lv.php new file mode 100644 index 0000000..363193d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/lv.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => '0 gadiem|:count gada|:count gadiem', + 'y' => '0 gadiem|:count gada|:count gadiem', + 'month' => '0 mÄ“neÅ¡iem|:count mÄ“neÅ¡a|:count mÄ“neÅ¡iem', + 'm' => '0 mÄ“neÅ¡iem|:count mÄ“neÅ¡a|:count mÄ“neÅ¡iem', + 'week' => '0 nedēļÄm|:count nedēļas|:count nedēļÄm', + 'w' => '0 nedēļÄm|:count nedēļas|:count nedēļÄm', + 'day' => '0 dienÄm|:count dienas|:count dienÄm', + 'd' => '0 dienÄm|:count dienas|:count dienÄm', + 'hour' => '0 stundÄm|:count stundas|:count stundÄm', + 'h' => '0 stundÄm|:count stundas|:count stundÄm', + 'minute' => '0 minÅ«tÄ“m|:count minÅ«tes|:count minÅ«tÄ“m', + 'min' => '0 minÅ«tÄ“m|:count minÅ«tes|:count minÅ«tÄ“m', + 'second' => '0 sekundÄ“m|:count sekundes|:count sekundÄ“m', + 's' => '0 sekundÄ“m|:count sekundes|:count sekundÄ“m', + 'ago' => 'pirms :time', + 'from_now' => 'pÄ“c :time', + 'after' => ':time vÄ“lÄk', + 'before' => ':time pirms', + + 'year_after' => '0 gadus|:count gadu|:count gadus', + 'month_after' => '0 mÄ“neÅ¡us|:count mÄ“nesi|:count mÄ“neÅ¡us', + 'week_after' => '0 nedēļas|:count nedēļu|:count nedēļas', + 'day_after' => '0 dienas|:count dienu|:count dienas', + 'hour_after' => '0 stundas|:count stundu|:count stundas', + 'minute_after' => '0 minÅ«tes|:count minÅ«ti|:count minÅ«tes', + 'second_after' => '0 sekundes|:count sekundi|:count sekundes', + + 'year_before' => '0 gadus|:count gadu|:count gadus', + 'month_before' => '0 mÄ“neÅ¡us|:count mÄ“nesi|:count mÄ“neÅ¡us', + 'week_before' => '0 nedēļas|:count nedēļu|:count nedēļas', + 'day_before' => '0 dienas|:count dienu|:count dienas', + 'hour_before' => '0 stundas|:count stundu|:count stundas', + 'minute_before' => '0 minÅ«tes|:count minÅ«ti|:count minÅ«tes', + 'second_before' => '0 sekundes|:count sekundi|:count sekundes', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/mk.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/mk.php new file mode 100644 index 0000000..c5ec12d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/mk.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count година|:count години', + 'month' => ':count меÑец|:count меÑеци', + 'week' => ':count Ñедмица|:count Ñедмици', + 'day' => ':count ден|:count дена', + 'hour' => ':count чаÑ|:count чаÑа', + 'minute' => ':count минута|:count минути', + 'second' => ':count Ñекунда|:count Ñекунди', + 'ago' => 'пред :time', + 'from_now' => ':time од Ñега', + 'after' => 'по :time', + 'before' => 'пред :time', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/mn.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/mn.php new file mode 100644 index 0000000..b26dce5 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/mn.php @@ -0,0 +1,62 @@ + + * + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @translator Batmandakh Erdenebileg + */ + +return array( + 'year' => ':count жил', + 'y' => ':count жил', + 'month' => ':count Ñар', + 'm' => ':count Ñар', + 'week' => ':count долоо хоног', + 'w' => ':count долоо хоног', + 'day' => ':count өдөр', + 'd' => ':count өдөр', + 'hour' => ':count цаг', + 'h' => ':countц', + 'minute' => ':count минут', + 'min' => ':countм', + 'second' => ':count Ñекунд', + 's' => ':countÑ', + + 'ago' => ':timeн өмнө', + 'year_ago' => ':count жилий', + 'month_ago' => ':count Ñары', + 'day_ago' => ':count хоногий', + 'hour_ago' => ':count цагий', + 'minute_ago' => ':count минуты', + 'second_ago' => ':count Ñекунды', + + 'from_now' => 'Ð¾Ð´Ð¾Ð¾Ð³Ð¾Ð¾Ñ :time', + 'year_from_now' => ':count жилийн дараа', + 'month_from_now' => ':count Ñарын дараа', + 'day_from_now' => ':count хоногийн дараа', + 'hour_from_now' => ':count цагийн дараа', + 'minute_from_now' => ':count минутын дараа', + 'second_from_now' => ':count Ñекундын дараа', + + // Does it required to make translation for before, after as follows? hmm, I think we've made it with ago and from now keywords already. Anyway, I've included it just in case of undesired action... + 'after' => ':timeн дараа', + 'year_after' => ':count жилий', + 'month_after' => ':count Ñары', + 'day_after' => ':count хоногий', + 'hour_after' => ':count цагий', + 'minute_after' => ':count минуты', + 'second_after' => ':count Ñекунды', + 'before' => ':timeн өмнө', + 'year_before' => ':count жилий', + 'month_before' => ':count Ñары', + 'day_before' => ':count хоногий', + 'hour_before' => ':count цагий', + 'minute_before' => ':count минуты', + 'second_before' => ':count Ñекунды', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ms.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ms.php new file mode 100644 index 0000000..ef57422 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ms.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count tahun', + 'y' => ':count tahun', + 'month' => ':count bulan', + 'm' => ':count bulan', + 'week' => ':count minggu', + 'w' => ':count minggu', + 'day' => ':count hari', + 'd' => ':count hari', + 'hour' => ':count jam', + 'h' => ':count jam', + 'minute' => ':count minit', + 'min' => ':count minit', + 'second' => ':count saat', + 's' => ':count saat', + 'ago' => ':time yang lalu', + 'from_now' => ':time dari sekarang', + 'after' => ':time selepas', + 'before' => ':time sebelum', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/my.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/my.php new file mode 100644 index 0000000..e8e491e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/my.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count နှစ်|:count နှစ်', + 'y' => ':count နှစ်|:count နှစ်', + 'month' => ':count လ|:count လ', + 'm' => ':count လ|:count လ', + 'week' => ':count ပá€á€º|:count ပá€á€º', + 'w' => ':count ပá€á€º|:count ပá€á€º', + 'day' => ':count ရက်|:count ရက်', + 'd' => ':count ရက်|:count ရက်', + 'hour' => ':count နာရီ|:count နာရီ', + 'h' => ':count နာရီ|:count နာရီ', + 'minute' => ':count မိနစ်|:count မိနစ်', + 'min' => ':count မိနစ်|:count မိနစ်', + 'second' => ':count စက္ကန့်|:count စက္ကန့်', + 's' => ':count စက္ကန့်|:count စက္ကန့်', + 'ago' => 'လွန်á€á€²á€·á€žá€±á€¬ :time က', + 'from_now' => 'ယá€á€¯á€™á€¾á€…áနောက် :time အကြာ', + 'after' => ':time ကြာပြီးနောက်', + 'before' => ':time မá€á€­á€¯á€„်á€á€„်', + 'diff_now' => 'အá€á€¯á€œá€±á€¸á€á€„်', + 'diff_yesterday' => 'မနေ့က', + 'diff_tomorrow' => 'မနက်ဖြန်', + 'diff_before_yesterday' => 'á€á€™á€¼á€”်နေ့က', + 'diff_after_tomorrow' => 'á€á€˜á€€á€ºá€á€«', + 'period_recurrences' => ':count ကြိမ်', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ne.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ne.php new file mode 100644 index 0000000..0b528df --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ne.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count वरà¥à¤·', + 'y' => ':count वरà¥à¤·', + 'month' => ':count महिना', + 'm' => ':count महिना', + 'week' => ':count हपà¥à¤¤à¤¾', + 'w' => ':count हपà¥à¤¤à¤¾', + 'day' => ':count दिन', + 'd' => ':count दिन', + 'hour' => ':count घणà¥à¤Ÿà¤¾', + 'h' => ':count घणà¥à¤Ÿà¤¾', + 'minute' => ':count मिनेट', + 'min' => ':count मिनेट', + 'second' => ':count सेकेणà¥à¤¡', + 's' => ':count सेकेणà¥à¤¡', + 'ago' => ':time पहिले', + 'from_now' => ':time देखि', + 'after' => ':time पछि', + 'before' => ':time अघि', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/nl.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/nl.php new file mode 100644 index 0000000..ec5a88e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/nl.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count jaar', + 'y' => ':count jaar', + 'month' => ':count maand|:count maanden', + 'm' => ':count maand|:count maanden', + 'week' => ':count week|:count weken', + 'w' => ':count week|:count weken', + 'day' => ':count dag|:count dagen', + 'd' => ':count dag|:count dagen', + 'hour' => ':count uur', + 'h' => ':count uur', + 'minute' => ':count minuut|:count minuten', + 'min' => ':count minuut|:count minuten', + 'second' => ':count seconde|:count seconden', + 's' => ':count seconde|:count seconden', + 'ago' => ':time geleden', + 'from_now' => 'over :time', + 'after' => ':time later', + 'before' => ':time eerder', + 'diff_now' => 'nu', + 'diff_yesterday' => 'gisteren', + 'diff_tomorrow' => 'morgen', + 'diff_after_tomorrow' => 'overmorgen', + 'diff_before_yesterday' => 'eergisteren', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/no.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/no.php new file mode 100644 index 0000000..a6ece06 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/no.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count Ã¥r|:count Ã¥r', + 'y' => ':count Ã¥r|:count Ã¥r', + 'month' => ':count mÃ¥ned|:count mÃ¥neder', + 'm' => ':count mÃ¥ned|:count mÃ¥neder', + 'week' => ':count uke|:count uker', + 'w' => ':count uke|:count uker', + 'day' => ':count dag|:count dager', + 'd' => ':count dag|:count dager', + 'hour' => ':count time|:count timer', + 'h' => ':count time|:count timer', + 'minute' => ':count minutt|:count minutter', + 'min' => ':count minutt|:count minutter', + 'second' => ':count sekund|:count sekunder', + 's' => ':count sekund|:count sekunder', + 'ago' => ':time siden', + 'from_now' => 'om :time', + 'after' => ':time etter', + 'before' => ':time før', + 'diff_now' => 'akkurat nÃ¥', + 'diff_yesterday' => 'i gÃ¥r', + 'diff_tomorrow' => 'i morgen', + 'diff_before_yesterday' => 'i forgÃ¥rs', + 'diff_after_tomorrow' => 'i overmorgen', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/oc.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/oc.php new file mode 100644 index 0000000..e89e94c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/oc.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +\Symfony\Component\Translation\PluralizationRules::set(function ($number) { + return $number == 1 ? 0 : 1; +}, 'oc'); + +return array( + 'year' => ':count an|:count ans', + 'y' => ':count an|:count ans', + 'month' => ':count mes|:count meses', + 'm' => ':count mes|:count meses', + 'week' => ':count setmana|:count setmanas', + 'w' => ':count setmana|:count setmanas', + 'day' => ':count jorn|:count jorns', + 'd' => ':count jorn|:count jorns', + 'hour' => ':count ora|:count oras', + 'h' => ':count ora|:count oras', + 'minute' => ':count minuta|:count minutas', + 'min' => ':count minuta|:count minutas', + 'second' => ':count segonda|:count segondas', + 's' => ':count segonda|:count segondas', + 'ago' => 'fa :time', + 'from_now' => 'dins :time', + 'after' => ':time aprèp', + 'before' => ':time abans', + 'diff_now' => 'ara meteis', + 'diff_yesterday' => 'ièr', + 'diff_tomorrow' => 'deman', + 'diff_before_yesterday' => 'ièr delà', + 'diff_after_tomorrow' => 'deman passat', + 'period_recurrences' => ':count còp|:count còps', + 'period_interval' => 'cada :interval', + 'period_start_date' => 'de :date', + 'period_end_date' => 'fins a :date', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/pl.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/pl.php new file mode 100644 index 0000000..2308af2 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/pl.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count rok|:count lata|:count lat', + 'y' => ':countr|:countl', + 'month' => ':count miesiÄ…c|:count miesiÄ…ce|:count miesiÄ™cy', + 'm' => ':countmies', + 'week' => ':count tydzieÅ„|:count tygodnie|:count tygodni', + 'w' => ':counttyg', + 'day' => ':count dzieÅ„|:count dni|:count dni', + 'd' => ':countd', + 'hour' => ':count godzina|:count godziny|:count godzin', + 'h' => ':countg', + 'minute' => ':count minuta|:count minuty|:count minut', + 'min' => ':countm', + 'second' => ':count sekunda|:count sekundy|:count sekund', + 's' => ':counts', + 'ago' => ':time temu', + 'from_now' => ':time od teraz', + 'after' => ':time po', + 'before' => ':time przed', + 'diff_now' => 'przed chwilÄ…', + 'diff_yesterday' => 'wczoraj', + 'diff_tomorrow' => 'jutro', + 'diff_before_yesterday' => 'przedwczoraj', + 'diff_after_tomorrow' => 'pojutrze', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ps.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ps.php new file mode 100644 index 0000000..15c3296 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ps.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count کال|:count کاله', + 'y' => ':countکال|:countکاله', + 'month' => ':count مياشت|:count مياشتي', + 'm' => ':countمياشت|:countمياشتي', + 'week' => ':count اونÛ|:count اونÛ', + 'w' => ':countاونÛ|:countاونÛ', + 'day' => ':count ورÚ|:count ورÚÙŠ', + 'd' => ':countورÚ|:countورÚÙŠ', + 'hour' => ':count ساعت|:count ساعته', + 'h' => ':countساعت|:countساعته', + 'minute' => ':count دقيقه|:count دقيقÛ', + 'min' => ':countدقيقه|:countدقيقÛ', + 'second' => ':count ثانيه|:count ثانيÛ', + 's' => ':countثانيه|:countثانيÛ', + 'ago' => ':time دمخه', + 'from_now' => ':time له اوس څخه', + 'after' => ':time وروسته', + 'before' => ':time دمخه', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/pt.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/pt.php new file mode 100644 index 0000000..392b121 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/pt.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count ano|:count anos', + 'y' => ':count ano|:count anos', + 'month' => ':count mês|:count meses', + 'm' => ':count mês|:count meses', + 'week' => ':count semana|:count semanas', + 'w' => ':count semana|:count semanas', + 'day' => ':count dia|:count dias', + 'd' => ':count dia|:count dias', + 'hour' => ':count hora|:count horas', + 'h' => ':count hora|:count horas', + 'minute' => ':count minuto|:count minutos', + 'min' => ':count minuto|:count minutos', + 'second' => ':count segundo|:count segundos', + 's' => ':count segundo|:count segundos', + 'ago' => ':time atrás', + 'from_now' => 'em :time', + 'after' => ':time depois', + 'before' => ':time antes', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/pt_BR.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/pt_BR.php new file mode 100644 index 0000000..1f84eac --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/pt_BR.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count ano|:count anos', + 'y' => ':counta|:counta', + 'month' => ':count mês|:count meses', + 'm' => ':countm|:countm', + 'week' => ':count semana|:count semanas', + 'w' => ':countsem|:countsem', + 'day' => ':count dia|:count dias', + 'd' => ':countd|:countd', + 'hour' => ':count hora|:count horas', + 'h' => ':counth|:counth', + 'minute' => ':count minuto|:count minutos', + 'min' => ':countmin|:countmin', + 'second' => ':count segundo|:count segundos', + 's' => ':counts|:counts', + 'ago' => 'há :time', + 'from_now' => 'em :time', + 'after' => 'após :time', + 'before' => ':time atrás', + 'diff_now' => 'agora', + 'diff_yesterday' => 'ontem', + 'diff_tomorrow' => 'amanhã', + 'diff_before_yesterday' => 'anteontem', + 'diff_after_tomorrow' => 'depois de amanhã', + 'period_recurrences' => 'uma|:count vez', + 'period_interval' => 'toda :interval', + 'period_start_date' => 'de :date', + 'period_end_date' => 'até :date', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ro.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ro.php new file mode 100644 index 0000000..cc16724 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ro.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => 'un an|:count ani|:count ani', + 'y' => 'un an|:count ani|:count ani', + 'month' => 'o lună|:count luni|:count luni', + 'm' => 'o lună|:count luni|:count luni', + 'week' => 'o săptămână|:count săptămâni|:count săptămâni', + 'w' => 'o săptămână|:count săptămâni|:count săptămâni', + 'day' => 'o zi|:count zile|:count zile', + 'd' => 'o zi|:count zile|:count zile', + 'hour' => 'o oră|:count ore|:count ore', + 'h' => 'o oră|:count ore|:count ore', + 'minute' => 'un minut|:count minute|:count minute', + 'min' => 'un minut|:count minute|:count minute', + 'second' => 'o secundă|:count secunde|:count secunde', + 's' => 'o secundă|:count secunde|:count secunde', + 'ago' => 'acum :time', + 'from_now' => ':time de acum', + 'after' => 'peste :time', + 'before' => 'acum :time', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ru.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ru.php new file mode 100644 index 0000000..6a83fb1 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ru.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count год|:count года|:count лет', + 'y' => ':count г|:count г|:count л', + 'month' => ':count меÑÑц|:count меÑÑца|:count меÑÑцев', + 'm' => ':count м|:count м|:count м', + 'week' => ':count неделю|:count недели|:count недель', + 'w' => ':count н|:count н|:count н', + 'day' => ':count день|:count днÑ|:count дней', + 'd' => ':count д|:count д|:count д', + 'hour' => ':count чаÑ|:count чаÑа|:count чаÑов', + 'h' => ':count ч|:count ч|:count ч', + 'minute' => ':count минуту|:count минуты|:count минут', + 'min' => ':count мин|:count мин|:count мин', + 'second' => ':count Ñекунду|:count Ñекунды|:count Ñекунд', + 's' => ':count Ñ|:count Ñ|:count Ñ', + 'ago' => ':time назад', + 'from_now' => 'через :time', + 'after' => ':time поÑле', + 'before' => ':time до', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sh.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sh.php new file mode 100644 index 0000000..57f287a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sh.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +\Symfony\Component\Translation\PluralizationRules::set(function ($number) { + return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); +}, 'sh'); + +return array( + 'year' => ':count godina|:count godine|:count godina', + 'y' => ':count godina|:count godine|:count godina', + 'month' => ':count mesec|:count meseca|:count meseci', + 'm' => ':count mesec|:count meseca|:count meseci', + 'week' => ':count nedelja|:count nedelje|:count nedelja', + 'w' => ':count nedelja|:count nedelje|:count nedelja', + 'day' => ':count dan|:count dana|:count dana', + 'd' => ':count dan|:count dana|:count dana', + 'hour' => ':count Äas|:count Äasa|:count Äasova', + 'h' => ':count Äas|:count Äasa|:count Äasova', + 'minute' => ':count minut|:count minuta|:count minuta', + 'min' => ':count minut|:count minuta|:count minuta', + 'second' => ':count sekund|:count sekunda|:count sekundi', + 's' => ':count sekund|:count sekunda|:count sekundi', + 'ago' => 'pre :time', + 'from_now' => 'za :time', + 'after' => 'nakon :time', + 'before' => ':time raniјe', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sk.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sk.php new file mode 100644 index 0000000..6101344 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sk.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => 'rok|:count roky|:count rokov', + 'y' => 'rok|:count roky|:count rokov', + 'month' => 'mesiac|:count mesiace|:count mesiacov', + 'm' => 'mesiac|:count mesiace|:count mesiacov', + 'week' => 'týždeň|:count týždne|:count týždňov', + 'w' => 'týždeň|:count týždne|:count týždňov', + 'day' => 'deň|:count dni|:count dní', + 'd' => 'deň|:count dni|:count dní', + 'hour' => 'hodinu|:count hodiny|:count hodín', + 'h' => 'hodinu|:count hodiny|:count hodín', + 'minute' => 'minútu|:count minúty|:count minút', + 'min' => 'minútu|:count minúty|:count minút', + 'second' => 'sekundu|:count sekundy|:count sekúnd', + 's' => 'sekundu|:count sekundy|:count sekúnd', + 'ago' => 'pred :time', + 'from_now' => 'za :time', + 'after' => 'o :time neskôr', + 'before' => ':time predtým', + 'year_ago' => 'rokom|:count rokmi|:count rokmi', + 'month_ago' => 'mesiacom|:count mesiacmi|:count mesiacmi', + 'week_ago' => 'týždňom|:count týždňami|:count týždňami', + 'day_ago' => 'dňom|:count dňami|:count dňami', + 'hour_ago' => 'hodinou|:count hodinami|:count hodinami', + 'minute_ago' => 'minútou|:count minútami|:count minútami', + 'second_ago' => 'sekundou|:count sekundami|:count sekundami', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sl.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sl.php new file mode 100644 index 0000000..06686d1 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sl.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count leto|:count leti|:count leta|:count let', + 'y' => ':count leto|:count leti|:count leta|:count let', + 'month' => ':count mesec|:count meseca|:count mesece|:count mesecev', + 'm' => ':count mesec|:count meseca|:count mesece|:count mesecev', + 'week' => ':count teden|:count tedna|:count tedne|:count tednov', + 'w' => ':count teden|:count tedna|:count tedne|:count tednov', + 'day' => ':count dan|:count dni|:count dni|:count dni', + 'd' => ':count dan|:count dni|:count dni|:count dni', + 'hour' => ':count uro|:count uri|:count ure|:count ur', + 'h' => ':count uro|:count uri|:count ure|:count ur', + 'minute' => ':count minuto|:count minuti|:count minute|:count minut', + 'min' => ':count minuto|:count minuti|:count minute|:count minut', + 'second' => ':count sekundo|:count sekundi|:count sekunde|:count sekund', + 's' => ':count sekundo|:count sekundi|:count sekunde|:count sekund', + 'year_ago' => ':count letom|:count leti|:count leti|:count leti', + 'month_ago' => ':count mesecem|:count meseci|:count meseci|:count meseci', + 'week_ago' => ':count tednom|:count tednoma|:count tedni|:count tedni', + 'day_ago' => ':count dnem|:count dnevoma|:count dnevi|:count dnevi', + 'hour_ago' => ':count uro|:count urama|:count urami|:count urami', + 'minute_ago' => ':count minuto|:count minutama|:count minutami|:count minutami', + 'second_ago' => ':count sekundo|:count sekundama|:count sekundami|:count sekundami', + 'ago' => 'pred :time', + 'from_now' => 'Äez :time', + 'after' => 'Äez :time', + 'before' => 'pred :time', + 'diff_now' => 'ravnokar', + 'diff_yesterday' => 'vÄeraj', + 'diff_tomorrow' => 'jutri', + 'diff_before_yesterday' => 'predvÄerajÅ¡njim', + 'diff_after_tomorrow' => 'pojutriÅ¡njem', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sq.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sq.php new file mode 100644 index 0000000..6e138a0 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sq.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count vit|:count vjet', + 'y' => ':count vit|:count vjet', + 'month' => ':count muaj|:count muaj', + 'm' => ':count muaj|:count muaj', + 'week' => ':count javë|:count javë', + 'w' => ':count javë|:count javë', + 'day' => ':count ditë|:count ditë', + 'd' => ':count ditë|:count ditë', + 'hour' => ':count orë|:count orë', + 'h' => ':count orë|:count orë', + 'minute' => ':count minutë|:count minuta', + 'min' => ':count minutë|:count minuta', + 'second' => ':count sekondë|:count sekonda', + 's' => ':count sekondë|:count sekonda', + 'ago' => ':time më parë', + 'from_now' => ':time nga tani', + 'after' => ':time pas', + 'before' => ':time para', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr.php new file mode 100644 index 0000000..5a10642 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count godina|:count godine|:count godina', + 'y' => ':count godina|:count godine|:count godina', + 'month' => ':count mesec|:count meseca|:count meseci', + 'm' => ':count mesec|:count meseca|:count meseci', + 'week' => ':count nedelja|:count nedelje|:count nedelja', + 'w' => ':count nedelja|:count nedelje|:count nedelja', + 'day' => ':count dan|:count dana|:count dana', + 'd' => ':count dan|:count dana|:count dana', + 'hour' => ':count sat|:count sata|:count sati', + 'h' => ':count sat|:count sata|:count sati', + 'minute' => ':count minut|:count minuta |:count minuta', + 'min' => ':count minut|:count minuta |:count minuta', + 'second' => ':count sekund|:count sekunde|:count sekunde', + 's' => ':count sekund|:count sekunde|:count sekunde', + 'ago' => 'pre :time', + 'from_now' => ':time od sada', + 'after' => 'nakon :time', + 'before' => 'pre :time', + + 'year_from_now' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina', + 'year_ago' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina', + + 'week_from_now' => '{1} :count nedelju|{2,3,4} :count nedelje|[5,Inf[ :count nedelja', + 'week_ago' => '{1} :count nedelju|{2,3,4} :count nedelje|[5,Inf[ :count nedelja', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl.php new file mode 100644 index 0000000..2db83ed --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[ :count година', + 'y' => ':count г.', + 'month' => '{1} :count меÑец|{2,3,4}:count меÑеца|[5,Inf[ :count меÑеци', + 'm' => ':count м.', + 'week' => '{1} :count недеља|{2,3,4}:count недеље|[5,Inf[ :count недеља', + 'w' => ':count нед.', + 'day' => '{1,21,31} :count дан|[2,Inf[ :count дана', + 'd' => ':count д.', + 'hour' => '{1,21} :count Ñат|{2,3,4,22,23,24}:count Ñата|[5,Inf[ :count Ñати', + 'h' => ':count ч.', + 'minute' => '{1,21,31,41,51} :count минут|[2,Inf[ :count минута', + 'min' => ':count мин.', + 'second' => '{1,21,31,41,51} :count Ñекунд|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count Ñекунде|[5,Inf[:count Ñекунди', + 's' => ':count Ñек.', + 'ago' => 'пре :time', + 'from_now' => 'за :time', + 'after' => ':time након', + 'before' => ':time пре', + + 'year_from_now' => '{1,21,31,41,51} :count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count године|[5,Inf[ :count година', + 'year_ago' => '{1,21,31,41,51} :count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count године|[5,Inf[ :count година', + + 'week_from_now' => '{1} :count недељу|{2,3,4} :count недеље|[5,Inf[ :count недеља', + 'week_ago' => '{1} :count недељу|{2,3,4} :count недеље|[5,Inf[ :count недеља', + + 'diff_now' => 'управо Ñада', + 'diff_yesterday' => 'јуче', + 'diff_tomorrow' => 'Ñутра', + 'diff_before_yesterday' => 'прекјуче', + 'diff_after_tomorrow' => 'прекоÑутра', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_ME.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_ME.php new file mode 100644 index 0000000..18214c4 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_ME.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[ :count година', + 'y' => ':count г.', + 'month' => '{1} :count мјеÑец|{2,3,4}:count мјеÑеца|[5,Inf[ :count мјеÑеци', + 'm' => ':count мј.', + 'week' => '{1} :count недјеља|{2,3,4}:count недјеље|[5,Inf[ :count недјеља', + 'w' => ':count нед.', + 'day' => '{1,21,31} :count дан|[2,Inf[ :count дана', + 'd' => ':count д.', + 'hour' => '{1,21} :count Ñат|{2,3,4,22,23,24}:count Ñата|[5,Inf[ :count Ñати', + 'h' => ':count ч.', + 'minute' => '{1,21,31,41,51} :count минут|[2,Inf[ :count минута', + 'min' => ':count мин.', + 'second' => '{1,21,31,41,51} :count Ñекунд|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count Ñекунде|[5,Inf[:count Ñекунди', + 's' => ':count Ñек.', + 'ago' => 'прије :time', + 'from_now' => 'за :time', + 'after' => ':time након', + 'before' => ':time прије', + + 'year_from_now' => '{1,21,31,41,51} :count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count године|[5,Inf[ :count година', + 'year_ago' => '{1,21,31,41,51} :count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count године|[5,Inf[ :count година', + + 'week_from_now' => '{1} :count недјељу|{2,3,4} :count недјеље|[5,Inf[ :count недјеља', + 'week_ago' => '{1} :count недјељу|{2,3,4} :count недјеље|[5,Inf[ :count недјеља', + + 'diff_now' => 'управо Ñада', + 'diff_yesterday' => 'јуче', + 'diff_tomorrow' => 'Ñутра', + 'diff_before_yesterday' => 'прекјуче', + 'diff_after_tomorrow' => 'прекоÑјутра', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_ME.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_ME.php new file mode 100644 index 0000000..2d2e288 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_ME.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count godine|[0,Inf[ :count godina', + 'y' => ':count g.', + 'month' => '{1} :count mjesec|{2,3,4}:count mjeseca|[5,Inf[ :count mjeseci', + 'm' => ':count mj.', + 'week' => '{1} :count nedjelja|{2,3,4}:count nedjelje|[5,Inf[ :count nedjelja', + 'w' => ':count ned.', + 'day' => '{1,21,31} :count dan|[2,Inf[ :count dana', + 'd' => ':count d.', + 'hour' => '{1,21} :count sat|{2,3,4,22,23,24}:count sata|[5,Inf[ :count sati', + 'h' => ':count Ä.', + 'minute' => '{1,21,31,41,51} :count minut|[2,Inf[ :count minuta', + 'min' => ':count min.', + 'second' => '{1,21,31,41,51} :count sekund|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count sekunde|[5,Inf[:count sekundi', + 's' => ':count sek.', + 'ago' => 'prije :time', + 'from_now' => 'za :time', + 'after' => ':time nakon', + 'before' => ':time prije', + + 'year_from_now' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina', + 'year_ago' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina', + + 'week_from_now' => '{1} :count nedjelju|{2,3,4} :count nedjelje|[5,Inf[ :count nedjelja', + 'week_ago' => '{1} :count nedjelju|{2,3,4} :count nedjelje|[5,Inf[ :count nedjelja', + + 'diff_now' => 'upravo sada', + 'diff_yesterday' => 'juÄe', + 'diff_tomorrow' => 'sutra', + 'diff_before_yesterday' => 'prekjuÄe', + 'diff_after_tomorrow' => 'preksutra', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_ME.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_ME.php new file mode 100644 index 0000000..7ebf6f0 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sr_ME.php @@ -0,0 +1,12 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return require __DIR__.'/sr_Latn_ME.php'; diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sv.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sv.php new file mode 100644 index 0000000..89a03b4 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sv.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count Ã¥r|:count Ã¥r', + 'y' => ':count Ã¥r|:count Ã¥r', + 'month' => ':count mÃ¥nad|:count mÃ¥nader', + 'm' => ':count mÃ¥nad|:count mÃ¥nader', + 'week' => ':count vecka|:count veckor', + 'w' => ':count vecka|:count veckor', + 'day' => ':count dag|:count dagar', + 'd' => ':count dag|:count dagar', + 'hour' => ':count timme|:count timmar', + 'h' => ':count timme|:count timmar', + 'minute' => ':count minut|:count minuter', + 'min' => ':count minut|:count minuter', + 'second' => ':count sekund|:count sekunder', + 's' => ':count sekund|:count sekunder', + 'ago' => ':time sedan', + 'from_now' => 'om :time', + 'after' => ':time efter', + 'before' => ':time före', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sw.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sw.php new file mode 100644 index 0000000..52f0342 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/sw.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => 'mwaka 1|miaka :count', + 'y' => 'mwaka 1|miaka :count', + 'month' => 'mwezi 1|miezi :count', + 'm' => 'mwezi 1|miezi :count', + 'week' => 'wiki 1|wiki :count', + 'w' => 'wiki 1|wiki :count', + 'day' => 'siku 1|siku :count', + 'd' => 'siku 1|siku :count', + 'hour' => 'saa 1|masaa :count', + 'h' => 'saa 1|masaa :count', + 'minute' => 'dakika 1|dakika :count', + 'min' => 'dakika 1|dakika :count', + 'second' => 'sekunde 1|sekunde :count', + 's' => 'sekunde 1|sekunde :count', + 'ago' => ':time ziliyopita', + 'from_now' => ':time kwanzia sasa', + 'after' => ':time baada', + 'before' => ':time kabla', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/th.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/th.php new file mode 100644 index 0000000..88bb4ac --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/th.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count ปี', + 'y' => ':count ปี', + 'month' => ':count เดือน', + 'm' => ':count เดือน', + 'week' => ':count สัปดาห์', + 'w' => ':count สัปดาห์', + 'day' => ':count วัน', + 'd' => ':count วัน', + 'hour' => ':count ชั่วโมง', + 'h' => ':count ชั่วโมง', + 'minute' => ':count นาที', + 'min' => ':count นาที', + 'second' => ':count วินาที', + 's' => ':count วินาที', + 'ago' => ':timeที่à¹à¸¥à¹‰à¸§', + 'from_now' => ':timeต่อจาà¸à¸™à¸µà¹‰', + 'after' => ':timeหลังจาà¸à¸™à¸µà¹‰', + 'before' => ':timeà¸à¹ˆà¸­à¸™', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/tr.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/tr.php new file mode 100644 index 0000000..6a9dfed --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/tr.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count yıl', + 'y' => ':count yıl', + 'month' => ':count ay', + 'm' => ':count ay', + 'week' => ':count hafta', + 'w' => ':count hafta', + 'day' => ':count gün', + 'd' => ':count gün', + 'hour' => ':count saat', + 'h' => ':count saat', + 'minute' => ':count dakika', + 'min' => ':count dakika', + 'second' => ':count saniye', + 's' => ':count saniye', + 'ago' => ':time önce', + 'from_now' => ':time sonra', + 'after' => ':time sonra', + 'before' => ':time önce', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/uk.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/uk.php new file mode 100644 index 0000000..8d08eaa --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/uk.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count рік|:count роки|:count років', + 'y' => ':count рік|:count роки|:count років', + 'month' => ':count міÑÑць|:count міÑÑці|:count міÑÑців', + 'm' => ':count міÑÑць|:count міÑÑці|:count міÑÑців', + 'week' => ':count тиждень|:count тижні|:count тижнів', + 'w' => ':count тиждень|:count тижні|:count тижнів', + 'day' => ':count день|:count дні|:count днів', + 'd' => ':count день|:count дні|:count днів', + 'hour' => ':count година|:count години|:count годин', + 'h' => ':count година|:count години|:count годин', + 'minute' => ':count хвилину|:count хвилини|:count хвилин', + 'min' => ':count хвилину|:count хвилини|:count хвилин', + 'second' => ':count Ñекунду|:count Ñекунди|:count Ñекунд', + 's' => ':count Ñекунду|:count Ñекунди|:count Ñекунд', + 'ago' => ':time тому', + 'from_now' => 'через :time', + 'after' => ':time піÑлÑ', + 'before' => ':time до', + 'diff_now' => 'щойно', + 'diff_yesterday' => 'вчора', + 'diff_tomorrow' => 'завтра', + 'diff_before_yesterday' => 'позавчора', + 'diff_after_tomorrow' => 'піÑлÑзавтра', + 'period_recurrences' => 'один раз|:count рази|:count разів', + 'period_interval' => 'кожні :interval', + 'period_start_date' => 'з :date', + 'period_end_date' => 'до :date', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ur.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ur.php new file mode 100644 index 0000000..3c5f7ed --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/ur.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count سال', + 'month' => ':count ماه', + 'week' => ':count ÛÙØªÛ’', + 'day' => ':count روز', + 'hour' => ':count گھنٹے', + 'minute' => ':count منٹ', + 'second' => ':count سیکنڈ', + 'ago' => ':time Ù¾ÛÙ„Û’', + 'from_now' => ':time بعد', + 'after' => ':time بعد', + 'before' => ':time Ù¾ÛÙ„Û’', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/uz.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/uz.php new file mode 100644 index 0000000..1cb6f71 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/uz.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count yil', + 'y' => ':count yil', + 'month' => ':count oy', + 'm' => ':count oy', + 'week' => ':count hafta', + 'w' => ':count hafta', + 'day' => ':count kun', + 'd' => ':count kun', + 'hour' => ':count soat', + 'h' => ':count soat', + 'minute' => ':count daqiqa', + 'min' => ':count daq', + 'second' => ':count soniya', + 's' => ':count s', + 'ago' => ':time avval', + 'from_now' => ':time dan keyin', + 'after' => ':time keyin', + 'before' => ':time oldin', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/vi.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/vi.php new file mode 100644 index 0000000..3f9838d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/vi.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':count năm', + 'y' => ':count năm', + 'month' => ':count tháng', + 'm' => ':count tháng', + 'week' => ':count tuần', + 'w' => ':count tuần', + 'day' => ':count ngày', + 'd' => ':count ngày', + 'hour' => ':count giá»', + 'h' => ':count giá»', + 'minute' => ':count phút', + 'min' => ':count phút', + 'second' => ':count giây', + 's' => ':count giây', + 'ago' => ':time trước', + 'from_now' => ':time từ bây giá»', + 'after' => ':time sau', + 'before' => ':time trước', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/zh.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/zh.php new file mode 100644 index 0000000..9e1f6ca --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/zh.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':countå¹´', + 'y' => ':countå¹´', + 'month' => ':count个月', + 'm' => ':count个月', + 'week' => ':count周', + 'w' => ':count周', + 'day' => ':count天', + 'd' => ':count天', + 'hour' => ':countå°æ—¶', + 'h' => ':countå°æ—¶', + 'minute' => ':count分钟', + 'min' => ':count分钟', + 'second' => ':countç§’', + 's' => ':countç§’', + 'ago' => ':timeå‰', + 'from_now' => 'è·çŽ°åœ¨:time', + 'after' => ':timeåŽ', + 'before' => ':timeå‰', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php new file mode 100644 index 0000000..c848723 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return array( + 'year' => ':countå¹´', + 'y' => ':countå¹´', + 'month' => ':count月', + 'm' => ':count月', + 'week' => ':count週', + 'w' => ':count週', + 'day' => ':count天', + 'd' => ':count天', + 'hour' => ':countå°æ™‚', + 'h' => ':countå°æ™‚', + 'minute' => ':count分é˜', + 'min' => ':count分é˜', + 'second' => ':countç§’', + 's' => ':countç§’', + 'ago' => ':timeå‰', + 'from_now' => 'è·ç¾åœ¨:time', + 'after' => ':time後', + 'before' => ':timeå‰', +); diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php new file mode 100644 index 0000000..4d83b0c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php @@ -0,0 +1,37 @@ +app['events']; + if ($events instanceof EventDispatcher || $events instanceof Dispatcher) { + $events->listen(class_exists('Illuminate\Foundation\Events\LocaleUpdated') ? 'Illuminate\Foundation\Events\LocaleUpdated' : 'locale.changed', function () use ($service) { + $service->updateLocale(); + }); + $service->updateLocale(); + } + } + + public function updateLocale() + { + $translator = $this->app['translator']; + if ($translator instanceof Translator || $translator instanceof IlluminateTranslator) { + Carbon::setLocale($translator->getLocale()); + } + } + + public function register() + { + // Needed for Laravel < 5.3 compatibility + } +} diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Translator.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Translator.php new file mode 100644 index 0000000..12115b0 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Translator.php @@ -0,0 +1,143 @@ +addLoader('array', new Translation\Loader\ArrayLoader()); + parent::__construct($locale, $formatter, $cacheDir, $debug); + } + + /** + * Reset messages of a locale (all locale if no locale passed). + * Remove custom messages and reload initial messages from matching + * file in Lang directory. + * + * @param string|null $locale + * + * @return bool + */ + public function resetMessages($locale = null) + { + if ($locale === null) { + static::$messages = array(); + + return true; + } + + if (file_exists($filename = __DIR__.'/Lang/'.$locale.'.php')) { + static::$messages[$locale] = require $filename; + $this->addResource('array', static::$messages[$locale], $locale); + + return true; + } + + return false; + } + + /** + * Init messages language from matching file in Lang directory. + * + * @param string $locale + * + * @return bool + */ + protected function loadMessagesFromFile($locale) + { + if (isset(static::$messages[$locale])) { + return true; + } + + return $this->resetMessages($locale); + } + + /** + * Set messages of a locale and take file first if present. + * + * @param string $locale + * @param array $messages + * + * @return $this + */ + public function setMessages($locale, $messages) + { + $this->loadMessagesFromFile($locale); + $this->addResource('array', $messages, $locale); + static::$messages[$locale] = array_merge( + isset(static::$messages[$locale]) ? static::$messages[$locale] : array(), + $messages + ); + + return $this; + } + + /** + * Get messages of a locale, if none given, return all the + * languages. + * + * @param string|null $locale + * + * @return array + */ + public function getMessages($locale = null) + { + return $locale === null ? static::$messages : static::$messages[$locale]; + } + + /** + * Set the current translator locale and indicate if the source locale file exists + * + * @param string $locale locale ex. en + * + * @return bool + */ + public function setLocale($locale) + { + $locale = preg_replace_callback('/[-_]([a-z]{2,})/', function ($matches) { + // _2-letters is a region, _3+-letters is a variant + return '_'.call_user_func(strlen($matches[1]) > 2 ? 'ucfirst' : 'strtoupper', $matches[1]); + }, strtolower($locale)); + + if ($this->loadMessagesFromFile($locale)) { + parent::setLocale($locale); + + return true; + } + + return false; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Upgrade.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Upgrade.php new file mode 100644 index 0000000..26449ff --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/Carbon/Upgrade.php @@ -0,0 +1,150 @@ + '5.8.0', + 'laravel/cashier' => '9.0.1', + 'illuminate/support' => '5.8.0', + 'laravel/dusk' => '5.0.0', + ); + + protected static $otherLibraries = array( + 'spatie/laravel-analytics' => '3.6.4', + 'jenssegers/date' => '3.5.0', + ); + + /** + * @param \UpdateHelper\UpdateHelper $helper + */ + public function check(UpdateHelper $helper) + { + $helper->write(array( + 'Carbon 1 is deprecated, see how to migrate to Carbon 2.', + 'https://carbon.nesbot.com/docs/#api-carbon-2', + )); + + if (static::SUGGEST_ON_UPDATE || static::ASK_ON_UPDATE || $helper->getIo()->isVerbose()) { + $laravelUpdate = array(); + + foreach (static::$laravelLibraries as $name => $version) { + if ($helper->hasAsDependency($name) && $helper->isDependencyLesserThan($name, $version)) { + $laravelUpdate[$name] = $version; + } + } + + if (count($laravelUpdate)) { + $output = array( + ' Please consider upgrading your Laravel dependencies to be compatible with Carbon 2:', + ); + + foreach ($laravelUpdate as $name => $version) { + $output[] = " - $name at least to version $version"; + } + + $output[] = ''; + $output[] = " If you can't update Laravel, check https://carbon.nesbot.com/ to see how to"; + $output[] = ' install Carbon 2 using alias version and our adapter kylekatarnls/laravel-carbon-2'; + $output[] = ''; + + $helper->write($output); + } + + foreach (static::$otherLibraries as $name => $version) { + if ($helper->hasAsDependency($name) && $helper->isDependencyLesserThan($name, $version)) { + $helper->write(" Please consider upgrading $name at least to $version to be compatible with Carbon 2.\n"); + } + } + + if (static::ASK_ON_UPDATE) { + static::askForUpgrade($helper); + + return; + } + } + + $path = implode(DIRECTORY_SEPARATOR, array('.', 'vendor', 'bin', 'upgrade-carbon')); + + if (!file_exists($path)) { + $path = realpath(__DIR__.'/../../bin/upgrade-carbon'); + } + + $helper->write( + ' You can run '.escapeshellarg($path). + ' to get help in updating carbon and other frameworks and libraries that depend on it.' + ); + } + + private static function getUpgradeQuestion($upgrades) + { + $message = "Do you want us to try the following upgrade:\n"; + + foreach ($upgrades as $name => $version) { + $message .= " - $name: $version\n"; + } + + return $message.'[Y/N] '; + } + + public static function askForUpgrade(UpdateHelper $helper, $upgradeIfNotInteractive = false) + { + $upgrades = array( + 'nesbot/carbon' => '^2.0.0', + ); + + foreach (array(static::$laravelLibraries, static::$otherLibraries) as $libraries) { + foreach ($libraries as $name => $version) { + if ($helper->hasAsDependency($name) && $helper->isDependencyLesserThan($name, $version)) { + $upgrades[$name] = "^$version"; + } + } + } + + $shouldUpgrade = $helper->isInteractive() + ? $helper->getIo()->askConfirmation(static::getUpgradeQuestion($upgrades)) + : $upgradeIfNotInteractive; + + if ($shouldUpgrade) { + $helper->setDependencyVersions($upgrades)->update(); + } + } + + public static function upgrade(ScriptEvent $event = null) + { + if (!$event) { + $composer = new Composer(); + $baseDir = __DIR__.'/../..'; + + if (file_exists("$baseDir/autoload.php")) { + $baseDir .= '/..'; + } + + $composer->setConfig(new Config(true, $baseDir)); + $event = new ScriptEvent( + 'upgrade-carbon', + $composer, + new ConsoleIO(new StringInput(''), new ConsoleOutput(), new HelperSet(array( + new QuestionHelper(), + ))) + ); + } + + static::askForUpgrade(new UpdateHelper($event), true); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/JsonSerializable.php b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/JsonSerializable.php new file mode 100644 index 0000000..d34060b --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/nesbot/carbon/src/JsonSerializable.php @@ -0,0 +1,18 @@ +json_encode, + * which is a value of any type other than a resource. + * + * @since 5.4.0 + */ + public function jsonSerialize(); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/LICENSE b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/LICENSE new file mode 100644 index 0000000..4cd8bdd --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/Mbstring.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/Mbstring.php new file mode 100644 index 0000000..15503bc --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/Mbstring.php @@ -0,0 +1,847 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Mbstring; + +/** + * Partial mbstring implementation in PHP, iconv based, UTF-8 centric. + * + * Implemented: + * - mb_chr - Returns a specific character from its Unicode code point + * - mb_convert_encoding - Convert character encoding + * - mb_convert_variables - Convert character code in variable(s) + * - mb_decode_mimeheader - Decode string in MIME header field + * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED + * - mb_decode_numericentity - Decode HTML numeric string reference to character + * - mb_encode_numericentity - Encode character to HTML numeric string reference + * - mb_convert_case - Perform case folding on a string + * - mb_detect_encoding - Detect character encoding + * - mb_get_info - Get internal settings of mbstring + * - mb_http_input - Detect HTTP input character encoding + * - mb_http_output - Set/Get HTTP output character encoding + * - mb_internal_encoding - Set/Get internal character encoding + * - mb_list_encodings - Returns an array of all supported encodings + * - mb_ord - Returns the Unicode code point of a character + * - mb_output_handler - Callback function converts character encoding in output buffer + * - mb_scrub - Replaces ill-formed byte sequences with substitute characters + * - mb_strlen - Get string length + * - mb_strpos - Find position of first occurrence of string in a string + * - mb_strrpos - Find position of last occurrence of a string in a string + * - mb_str_split - Convert a string to an array + * - mb_strtolower - Make a string lowercase + * - mb_strtoupper - Make a string uppercase + * - mb_substitute_character - Set/Get substitution character + * - mb_substr - Get part of string + * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive + * - mb_stristr - Finds first occurrence of a string within another, case insensitive + * - mb_strrchr - Finds the last occurrence of a character in a string within another + * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive + * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive + * - mb_strstr - Finds first occurrence of a string within another + * - mb_strwidth - Return width of string + * - mb_substr_count - Count the number of substring occurrences + * + * Not implemented: + * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more) + * - mb_ereg_* - Regular expression with multibyte support + * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable + * - mb_preferred_mime_name - Get MIME charset string + * - mb_regex_encoding - Returns current encoding for multibyte regex as string + * - mb_regex_set_options - Set/Get the default options for mbregex functions + * - mb_send_mail - Send encoded mail + * - mb_split - Split multibyte string using regular expression + * - mb_strcut - Get part of string + * - mb_strimwidth - Get truncated string with specified width + * + * @author Nicolas Grekas + * + * @internal + */ +final class Mbstring +{ + const MB_CASE_FOLD = PHP_INT_MAX; + + private static $encodingList = array('ASCII', 'UTF-8'); + private static $language = 'neutral'; + private static $internalEncoding = 'UTF-8'; + private static $caseFold = array( + array('µ', 'Å¿', "\xCD\x85", 'Ï‚', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"), + array('μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'Ï€', 'κ', 'Ï', 'ε', "\xE1\xB9\xA1", 'ι'), + ); + + public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) + { + if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) { + $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); + } else { + $fromEncoding = self::getEncoding($fromEncoding); + } + + $toEncoding = self::getEncoding($toEncoding); + + if ('BASE64' === $fromEncoding) { + $s = base64_decode($s); + $fromEncoding = $toEncoding; + } + + if ('BASE64' === $toEncoding) { + return base64_encode($s); + } + + if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) { + if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) { + $fromEncoding = 'Windows-1252'; + } + if ('UTF-8' !== $fromEncoding) { + $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s); + } + + return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s); + } + + if ('HTML-ENTITIES' === $fromEncoding) { + $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8'); + $fromEncoding = 'UTF-8'; + } + + return iconv($fromEncoding, $toEncoding.'//IGNORE', $s); + } + + public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) + { + $vars = array(&$a, &$b, &$c, &$d, &$e, &$f); + + $ok = true; + array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) { + if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) { + $ok = false; + } + }); + + return $ok ? $fromEncoding : false; + } + + public static function mb_decode_mimeheader($s) + { + return iconv_mime_decode($s, 2, self::$internalEncoding); + } + + public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) + { + trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING); + } + + public static function mb_decode_numericentity($s, $convmap, $encoding = null) + { + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { + trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING); + + return null; + } + + if (!\is_array($convmap) || !$convmap) { + return false; + } + + if (null !== $encoding && !\is_scalar($encoding)) { + trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING); + + return ''; // Instead of null (cf. mb_encode_numericentity). + } + + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + $cnt = floor(\count($convmap) / 4) * 4; + + for ($i = 0; $i < $cnt; $i += 4) { + // collector_decode_htmlnumericentity ignores $convmap[$i + 3] + $convmap[$i] += $convmap[$i + 2]; + $convmap[$i + 1] += $convmap[$i + 2]; + } + + $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) { + $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1]; + for ($i = 0; $i < $cnt; $i += 4) { + if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) { + return Mbstring::mb_chr($c - $convmap[$i + 2]); + } + } + + return $m[0]; + }, $s); + + if (null === $encoding) { + return $s; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $s); + } + + public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) + { + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { + trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING); + + return null; + } + + if (!\is_array($convmap) || !$convmap) { + return false; + } + + if (null !== $encoding && !\is_scalar($encoding)) { + trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING); + + return null; // Instead of '' (cf. mb_decode_numericentity). + } + + if (null !== $is_hex && !\is_scalar($is_hex)) { + trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', E_USER_WARNING); + + return null; + } + + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); + + $cnt = floor(\count($convmap) / 4) * 4; + $i = 0; + $len = \strlen($s); + $result = ''; + + while ($i < $len) { + $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + $i += $ulen; + $c = self::mb_ord($uchr); + + for ($j = 0; $j < $cnt; $j += 4) { + if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) { + $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3]; + $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';'; + continue 2; + } + } + $result .= $uchr; + } + + if (null === $encoding) { + return $result; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $result); + } + + public static function mb_convert_case($s, $mode, $encoding = null) + { + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + if (MB_CASE_TITLE == $mode) { + static $titleRegexp = null; + if (null === $titleRegexp) { + $titleRegexp = self::getData('titleCaseRegexp'); + } + $s = preg_replace_callback($titleRegexp, array(__CLASS__, 'title_case'), $s); + } else { + if (MB_CASE_UPPER == $mode) { + static $upper = null; + if (null === $upper) { + $upper = self::getData('upperCase'); + } + $map = $upper; + } else { + if (self::MB_CASE_FOLD === $mode) { + $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s); + } + + static $lower = null; + if (null === $lower) { + $lower = self::getData('lowerCase'); + } + $map = $lower; + } + + static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); + + $i = 0; + $len = \strlen($s); + + while ($i < $len) { + $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + $i += $ulen; + + if (isset($map[$uchr])) { + $uchr = $map[$uchr]; + $nlen = \strlen($uchr); + + if ($nlen == $ulen) { + $nlen = $i; + do { + $s[--$nlen] = $uchr[--$ulen]; + } while ($ulen); + } else { + $s = substr_replace($s, $uchr, $i - $ulen, $ulen); + $len += $nlen - $ulen; + $i += $nlen - $ulen; + } + } + } + } + + if (null === $encoding) { + return $s; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $s); + } + + public static function mb_internal_encoding($encoding = null) + { + if (null === $encoding) { + return self::$internalEncoding; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) { + self::$internalEncoding = $encoding; + + return true; + } + + return false; + } + + public static function mb_language($lang = null) + { + if (null === $lang) { + return self::$language; + } + + switch ($lang = strtolower($lang)) { + case 'uni': + case 'neutral': + self::$language = $lang; + + return true; + } + + return false; + } + + public static function mb_list_encodings() + { + return array('UTF-8'); + } + + public static function mb_encoding_aliases($encoding) + { + switch (strtoupper($encoding)) { + case 'UTF8': + case 'UTF-8': + return array('utf8'); + } + + return false; + } + + public static function mb_check_encoding($var = null, $encoding = null) + { + if (null === $encoding) { + if (null === $var) { + return false; + } + $encoding = self::$internalEncoding; + } + + return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var); + } + + public static function mb_detect_encoding($str, $encodingList = null, $strict = false) + { + if (null === $encodingList) { + $encodingList = self::$encodingList; + } else { + if (!\is_array($encodingList)) { + $encodingList = array_map('trim', explode(',', $encodingList)); + } + $encodingList = array_map('strtoupper', $encodingList); + } + + foreach ($encodingList as $enc) { + switch ($enc) { + case 'ASCII': + if (!preg_match('/[\x80-\xFF]/', $str)) { + return $enc; + } + break; + + case 'UTF8': + case 'UTF-8': + if (preg_match('//u', $str)) { + return 'UTF-8'; + } + break; + + default: + if (0 === strncmp($enc, 'ISO-8859-', 9)) { + return $enc; + } + } + } + + return false; + } + + public static function mb_detect_order($encodingList = null) + { + if (null === $encodingList) { + return self::$encodingList; + } + + if (!\is_array($encodingList)) { + $encodingList = array_map('trim', explode(',', $encodingList)); + } + $encodingList = array_map('strtoupper', $encodingList); + + foreach ($encodingList as $enc) { + switch ($enc) { + default: + if (strncmp($enc, 'ISO-8859-', 9)) { + return false; + } + // no break + case 'ASCII': + case 'UTF8': + case 'UTF-8': + } + } + + self::$encodingList = $encodingList; + + return true; + } + + public static function mb_strlen($s, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return \strlen($s); + } + + return @iconv_strlen($s, $encoding); + } + + public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return strpos($haystack, $needle, $offset); + } + + $needle = (string) $needle; + if ('' === $needle) { + trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING); + + return false; + } + + return iconv_strpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return strrpos($haystack, $needle, $offset); + } + + if ($offset != (int) $offset) { + $offset = 0; + } elseif ($offset = (int) $offset) { + if ($offset < 0) { + if (0 > $offset += self::mb_strlen($needle)) { + $haystack = self::mb_substr($haystack, 0, $offset, $encoding); + } + $offset = 0; + } else { + $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding); + } + } + + $pos = iconv_strrpos($haystack, $needle, $encoding); + + return false !== $pos ? $offset + $pos : false; + } + + public static function mb_str_split($string, $split_length = 1, $encoding = null) + { + if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) { + trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', E_USER_WARNING); + + return null; + } + + if (1 > $split_length = (int) $split_length) { + trigger_error('The length of each segment must be greater than zero', E_USER_WARNING); + + return false; + } + + if (null === $encoding) { + $encoding = mb_internal_encoding(); + } + + if ('UTF-8' === $encoding = self::getEncoding($encoding)) { + $rx = '/('; + while (65535 < $split_length) { + $rx .= '.{65535}'; + $split_length -= 65535; + } + $rx .= '.{'.$split_length.'})/us'; + + return preg_split($rx, $string, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + } + + $result = array(); + $length = mb_strlen($string, $encoding); + + for ($i = 0; $i < $length; $i += $split_length) { + $result[] = mb_substr($string, $i, $split_length, $encoding); + } + + return $result; + } + + public static function mb_strtolower($s, $encoding = null) + { + return self::mb_convert_case($s, MB_CASE_LOWER, $encoding); + } + + public static function mb_strtoupper($s, $encoding = null) + { + return self::mb_convert_case($s, MB_CASE_UPPER, $encoding); + } + + public static function mb_substitute_character($c = null) + { + if (0 === strcasecmp($c, 'none')) { + return true; + } + + return null !== $c ? false : 'none'; + } + + public static function mb_substr($s, $start, $length = null, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return (string) substr($s, $start, null === $length ? 2147483647 : $length); + } + + if ($start < 0) { + $start = iconv_strlen($s, $encoding) + $start; + if ($start < 0) { + $start = 0; + } + } + + if (null === $length) { + $length = 2147483647; + } elseif ($length < 0) { + $length = iconv_strlen($s, $encoding) + $length - $start; + if ($length < 0) { + return ''; + } + } + + return (string) iconv_substr($s, $start, $length, $encoding); + } + + public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) + { + $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); + $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); + + return self::mb_strpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_stristr($haystack, $needle, $part = false, $encoding = null) + { + $pos = self::mb_stripos($haystack, $needle, 0, $encoding); + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return strrchr($haystack, $needle, $part); + } + $needle = self::mb_substr($needle, 0, 1, $encoding); + $pos = iconv_strrpos($haystack, $needle, $encoding); + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null) + { + $needle = self::mb_substr($needle, 0, 1, $encoding); + $pos = self::mb_strripos($haystack, $needle, $encoding); + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) + { + $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); + $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); + + return self::mb_strrpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_strstr($haystack, $needle, $part = false, $encoding = null) + { + $pos = strpos($haystack, $needle); + if (false === $pos) { + return false; + } + if ($part) { + return substr($haystack, 0, $pos); + } + + return substr($haystack, $pos); + } + + public static function mb_get_info($type = 'all') + { + $info = array( + 'internal_encoding' => self::$internalEncoding, + 'http_output' => 'pass', + 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)', + 'func_overload' => 0, + 'func_overload_list' => 'no overload', + 'mail_charset' => 'UTF-8', + 'mail_header_encoding' => 'BASE64', + 'mail_body_encoding' => 'BASE64', + 'illegal_chars' => 0, + 'encoding_translation' => 'Off', + 'language' => self::$language, + 'detect_order' => self::$encodingList, + 'substitute_character' => 'none', + 'strict_detection' => 'Off', + ); + + if ('all' === $type) { + return $info; + } + if (isset($info[$type])) { + return $info[$type]; + } + + return false; + } + + public static function mb_http_input($type = '') + { + return false; + } + + public static function mb_http_output($encoding = null) + { + return null !== $encoding ? 'pass' === $encoding : 'pass'; + } + + public static function mb_strwidth($s, $encoding = null) + { + $encoding = self::getEncoding($encoding); + + if ('UTF-8' !== $encoding) { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide); + + return ($wide << 1) + iconv_strlen($s, 'UTF-8'); + } + + public static function mb_substr_count($haystack, $needle, $encoding = null) + { + return substr_count($haystack, $needle); + } + + public static function mb_output_handler($contents, $status) + { + return $contents; + } + + public static function mb_chr($code, $encoding = null) + { + if (0x80 > $code %= 0x200000) { + $s = \chr($code); + } elseif (0x800 > $code) { + $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); + } elseif (0x10000 > $code) { + $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } else { + $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } + + if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { + $s = mb_convert_encoding($s, $encoding, 'UTF-8'); + } + + return $s; + } + + public static function mb_ord($s, $encoding = null) + { + if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { + $s = mb_convert_encoding($s, 'UTF-8', $encoding); + } + + if (1 === \strlen($s)) { + return \ord($s); + } + + $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; + if (0xF0 <= $code) { + return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; + } + if (0xE0 <= $code) { + return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; + } + if (0xC0 <= $code) { + return (($code - 0xC0) << 6) + $s[2] - 0x80; + } + + return $code; + } + + private static function getSubpart($pos, $part, $haystack, $encoding) + { + if (false === $pos) { + return false; + } + if ($part) { + return self::mb_substr($haystack, 0, $pos, $encoding); + } + + return self::mb_substr($haystack, $pos, null, $encoding); + } + + private static function html_encoding_callback(array $m) + { + $i = 1; + $entities = ''; + $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8')); + + while (isset($m[$i])) { + if (0x80 > $m[$i]) { + $entities .= \chr($m[$i++]); + continue; + } + if (0xF0 <= $m[$i]) { + $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; + } elseif (0xE0 <= $m[$i]) { + $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; + } else { + $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80; + } + + $entities .= '&#'.$c.';'; + } + + return $entities; + } + + private static function title_case(array $s) + { + return self::mb_convert_case($s[1], MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], MB_CASE_LOWER, 'UTF-8'); + } + + private static function getData($file) + { + if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { + return require $file; + } + + return false; + } + + private static function getEncoding($encoding) + { + if (null === $encoding) { + return self::$internalEncoding; + } + + if ('UTF-8' === $encoding) { + return 'UTF-8'; + } + + $encoding = strtoupper($encoding); + + if ('8BIT' === $encoding || 'BINARY' === $encoding) { + return 'CP850'; + } + + if ('UTF8' === $encoding) { + return 'UTF-8'; + } + + return $encoding; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/README.md b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/README.md new file mode 100644 index 0000000..4efb599 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/README.md @@ -0,0 +1,13 @@ +Symfony Polyfill / Mbstring +=========================== + +This component provides a partial, native PHP implementation for the +[Mbstring](https://php.net/mbstring) extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php new file mode 100644 index 0000000..e6fbfa6 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php @@ -0,0 +1,1096 @@ + 'a', + 'B' => 'b', + 'C' => 'c', + 'D' => 'd', + 'E' => 'e', + 'F' => 'f', + 'G' => 'g', + 'H' => 'h', + 'I' => 'i', + 'J' => 'j', + 'K' => 'k', + 'L' => 'l', + 'M' => 'm', + 'N' => 'n', + 'O' => 'o', + 'P' => 'p', + 'Q' => 'q', + 'R' => 'r', + 'S' => 's', + 'T' => 't', + 'U' => 'u', + 'V' => 'v', + 'W' => 'w', + 'X' => 'x', + 'Y' => 'y', + 'Z' => 'z', + 'À' => 'à', + 'Ã' => 'á', + 'Â' => 'â', + 'Ã' => 'ã', + 'Ä' => 'ä', + 'Ã…' => 'Ã¥', + 'Æ' => 'æ', + 'Ç' => 'ç', + 'È' => 'è', + 'É' => 'é', + 'Ê' => 'ê', + 'Ë' => 'ë', + 'ÃŒ' => 'ì', + 'Ã' => 'í', + 'ÃŽ' => 'î', + 'Ã' => 'ï', + 'Ã' => 'ð', + 'Ñ' => 'ñ', + 'Ã’' => 'ò', + 'Ó' => 'ó', + 'Ô' => 'ô', + 'Õ' => 'õ', + 'Ö' => 'ö', + 'Ø' => 'ø', + 'Ù' => 'ù', + 'Ú' => 'ú', + 'Û' => 'û', + 'Ü' => 'ü', + 'Ã' => 'ý', + 'Þ' => 'þ', + 'Ä€' => 'Ä', + 'Ä‚' => 'ă', + 'Ä„' => 'Ä…', + 'Ć' => 'ć', + 'Ĉ' => 'ĉ', + 'ÄŠ' => 'Ä‹', + 'ÄŒ' => 'Ä', + 'ÄŽ' => 'Ä', + 'Ä' => 'Ä‘', + 'Ä’' => 'Ä“', + 'Ä”' => 'Ä•', + 'Ä–' => 'Ä—', + 'Ę' => 'Ä™', + 'Äš' => 'Ä›', + 'Äœ' => 'Ä', + 'Äž' => 'ÄŸ', + 'Ä ' => 'Ä¡', + 'Ä¢' => 'Ä£', + 'Ĥ' => 'Ä¥', + 'Ħ' => 'ħ', + 'Ĩ' => 'Ä©', + 'Ī' => 'Ä«', + 'Ĭ' => 'Ä­', + 'Ä®' => 'į', + 'İ' => 'i', + 'IJ' => 'ij', + 'Ä´' => 'ĵ', + 'Ķ' => 'Ä·', + 'Ĺ' => 'ĺ', + 'Ä»' => 'ļ', + 'Ľ' => 'ľ', + 'Ä¿' => 'Å€', + 'Å' => 'Å‚', + 'Ń' => 'Å„', + 'Å…' => 'ņ', + 'Ň' => 'ň', + 'ÅŠ' => 'Å‹', + 'ÅŒ' => 'Å', + 'ÅŽ' => 'Å', + 'Å' => 'Å‘', + 'Å’' => 'Å“', + 'Å”' => 'Å•', + 'Å–' => 'Å—', + 'Ř' => 'Å™', + 'Åš' => 'Å›', + 'Åœ' => 'Å', + 'Åž' => 'ÅŸ', + 'Å ' => 'Å¡', + 'Å¢' => 'Å£', + 'Ť' => 'Å¥', + 'Ŧ' => 'ŧ', + 'Ũ' => 'Å©', + 'Ū' => 'Å«', + 'Ŭ' => 'Å­', + 'Å®' => 'ů', + 'Ű' => 'ű', + 'Ų' => 'ų', + 'Å´' => 'ŵ', + 'Ŷ' => 'Å·', + 'Ÿ' => 'ÿ', + 'Ź' => 'ź', + 'Å»' => 'ż', + 'Ž' => 'ž', + 'Æ' => 'É“', + 'Æ‚' => 'ƃ', + 'Æ„' => 'Æ…', + 'Ɔ' => 'É”', + 'Ƈ' => 'ƈ', + 'Ɖ' => 'É–', + 'ÆŠ' => 'É—', + 'Æ‹' => 'ÆŒ', + 'ÆŽ' => 'Ç', + 'Æ' => 'É™', + 'Æ' => 'É›', + 'Æ‘' => 'Æ’', + 'Æ“' => 'É ', + 'Æ”' => 'É£', + 'Æ–' => 'É©', + 'Æ—' => 'ɨ', + 'Ƙ' => 'Æ™', + 'Æœ' => 'ɯ', + 'Æ' => 'ɲ', + 'ÆŸ' => 'ɵ', + 'Æ ' => 'Æ¡', + 'Æ¢' => 'Æ£', + 'Ƥ' => 'Æ¥', + 'Ʀ' => 'Ê€', + 'Ƨ' => 'ƨ', + 'Æ©' => 'ʃ', + 'Ƭ' => 'Æ­', + 'Æ®' => 'ʈ', + 'Ư' => 'ư', + 'Ʊ' => 'ÊŠ', + 'Ʋ' => 'Ê‹', + 'Ƴ' => 'Æ´', + 'Ƶ' => 'ƶ', + 'Æ·' => 'Ê’', + 'Ƹ' => 'ƹ', + 'Ƽ' => 'ƽ', + 'Ç„' => 'dž', + 'Ç…' => 'dž', + 'LJ' => 'lj', + 'Lj' => 'lj', + 'ÇŠ' => 'ÇŒ', + 'Ç‹' => 'ÇŒ', + 'Ç' => 'ÇŽ', + 'Ç' => 'Ç', + 'Ç‘' => 'Ç’', + 'Ç“' => 'Ç”', + 'Ç•' => 'Ç–', + 'Ç—' => 'ǘ', + 'Ç™' => 'Çš', + 'Ç›' => 'Çœ', + 'Çž' => 'ÇŸ', + 'Ç ' => 'Ç¡', + 'Ç¢' => 'Ç£', + 'Ǥ' => 'Ç¥', + 'Ǧ' => 'ǧ', + 'Ǩ' => 'Ç©', + 'Ǫ' => 'Ç«', + 'Ǭ' => 'Ç­', + 'Ç®' => 'ǯ', + 'DZ' => 'dz', + 'Dz' => 'dz', + 'Ç´' => 'ǵ', + 'Ƕ' => 'Æ•', + 'Ç·' => 'Æ¿', + 'Ǹ' => 'ǹ', + 'Ǻ' => 'Ç»', + 'Ǽ' => 'ǽ', + 'Ǿ' => 'Ç¿', + 'È€' => 'È', + 'È‚' => 'ȃ', + 'È„' => 'È…', + 'Ȇ' => 'ȇ', + 'Ȉ' => 'ȉ', + 'ÈŠ' => 'È‹', + 'ÈŒ' => 'È', + 'ÈŽ' => 'È', + 'È' => 'È‘', + 'È’' => 'È“', + 'È”' => 'È•', + 'È–' => 'È—', + 'Ș' => 'È™', + 'Èš' => 'È›', + 'Èœ' => 'È', + 'Èž' => 'ÈŸ', + 'È ' => 'Æž', + 'È¢' => 'È£', + 'Ȥ' => 'È¥', + 'Ȧ' => 'ȧ', + 'Ȩ' => 'È©', + 'Ȫ' => 'È«', + 'Ȭ' => 'È­', + 'È®' => 'ȯ', + 'Ȱ' => 'ȱ', + 'Ȳ' => 'ȳ', + 'Ⱥ' => 'â±¥', + 'È»' => 'ȼ', + 'Ƚ' => 'Æš', + 'Ⱦ' => 'ⱦ', + 'É' => 'É‚', + 'Ƀ' => 'Æ€', + 'É„' => 'ʉ', + 'É…' => 'ÊŒ', + 'Ɇ' => 'ɇ', + 'Ɉ' => 'ɉ', + 'ÉŠ' => 'É‹', + 'ÉŒ' => 'É', + 'ÉŽ' => 'É', + 'Ͱ' => 'ͱ', + 'Ͳ' => 'ͳ', + 'Ͷ' => 'Í·', + 'Í¿' => 'ϳ', + 'Ά' => 'ά', + 'Έ' => 'έ', + 'Ή' => 'ή', + 'Ί' => 'ί', + 'ÎŒ' => 'ÏŒ', + 'ÎŽ' => 'Ï', + 'Î' => 'ÏŽ', + 'Α' => 'α', + 'Î’' => 'β', + 'Γ' => 'γ', + 'Δ' => 'δ', + 'Ε' => 'ε', + 'Ζ' => 'ζ', + 'Η' => 'η', + 'Θ' => 'θ', + 'Ι' => 'ι', + 'Κ' => 'κ', + 'Λ' => 'λ', + 'Μ' => 'μ', + 'Î' => 'ν', + 'Ξ' => 'ξ', + 'Ο' => 'ο', + 'Π' => 'Ï€', + 'Ρ' => 'Ï', + 'Σ' => 'σ', + 'Τ' => 'Ï„', + 'Î¥' => 'Ï…', + 'Φ' => 'φ', + 'Χ' => 'χ', + 'Ψ' => 'ψ', + 'Ω' => 'ω', + 'Ϊ' => 'ÏŠ', + 'Ϋ' => 'Ï‹', + 'Ï' => 'Ï—', + 'Ϙ' => 'Ï™', + 'Ïš' => 'Ï›', + 'Ïœ' => 'Ï', + 'Ïž' => 'ÏŸ', + 'Ï ' => 'Ï¡', + 'Ï¢' => 'Ï£', + 'Ϥ' => 'Ï¥', + 'Ϧ' => 'ϧ', + 'Ϩ' => 'Ï©', + 'Ϫ' => 'Ï«', + 'Ϭ' => 'Ï­', + 'Ï®' => 'ϯ', + 'Ï´' => 'θ', + 'Ï·' => 'ϸ', + 'Ϲ' => 'ϲ', + 'Ϻ' => 'Ï»', + 'Ͻ' => 'Í»', + 'Ͼ' => 'ͼ', + 'Ï¿' => 'ͽ', + 'Ѐ' => 'Ñ', + 'Ð' => 'Ñ‘', + 'Ђ' => 'Ñ’', + 'Ѓ' => 'Ñ“', + 'Є' => 'Ñ”', + 'Ð…' => 'Ñ•', + 'І' => 'Ñ–', + 'Ї' => 'Ñ—', + 'Ј' => 'ј', + 'Љ' => 'Ñ™', + 'Њ' => 'Ñš', + 'Ћ' => 'Ñ›', + 'ÐŒ' => 'Ñœ', + 'Ð' => 'Ñ', + 'ÐŽ' => 'Ñž', + 'Ð' => 'ÑŸ', + 'Ð' => 'а', + 'Б' => 'б', + 'Ð’' => 'в', + 'Г' => 'г', + 'Д' => 'д', + 'Е' => 'е', + 'Ж' => 'ж', + 'З' => 'з', + 'И' => 'и', + 'Й' => 'й', + 'К' => 'к', + 'Л' => 'л', + 'М' => 'м', + 'Ð' => 'н', + 'О' => 'о', + 'П' => 'п', + 'Р' => 'Ñ€', + 'С' => 'Ñ', + 'Т' => 'Ñ‚', + 'У' => 'у', + 'Ф' => 'Ñ„', + 'Ð¥' => 'Ñ…', + 'Ц' => 'ц', + 'Ч' => 'ч', + 'Ш' => 'ш', + 'Щ' => 'щ', + 'Ъ' => 'ÑŠ', + 'Ы' => 'Ñ‹', + 'Ь' => 'ÑŒ', + 'Э' => 'Ñ', + 'Ю' => 'ÑŽ', + 'Я' => 'Ñ', + 'Ñ ' => 'Ñ¡', + 'Ñ¢' => 'Ñ£', + 'Ѥ' => 'Ñ¥', + 'Ѧ' => 'ѧ', + 'Ѩ' => 'Ñ©', + 'Ѫ' => 'Ñ«', + 'Ѭ' => 'Ñ­', + 'Ñ®' => 'ѯ', + 'Ѱ' => 'ѱ', + 'Ѳ' => 'ѳ', + 'Ñ´' => 'ѵ', + 'Ѷ' => 'Ñ·', + 'Ѹ' => 'ѹ', + 'Ѻ' => 'Ñ»', + 'Ѽ' => 'ѽ', + 'Ѿ' => 'Ñ¿', + 'Ò€' => 'Ò', + 'ÒŠ' => 'Ò‹', + 'ÒŒ' => 'Ò', + 'ÒŽ' => 'Ò', + 'Ò' => 'Ò‘', + 'Ò’' => 'Ò“', + 'Ò”' => 'Ò•', + 'Ò–' => 'Ò—', + 'Ò˜' => 'Ò™', + 'Òš' => 'Ò›', + 'Òœ' => 'Ò', + 'Òž' => 'ÒŸ', + 'Ò ' => 'Ò¡', + 'Ò¢' => 'Ò£', + 'Ò¤' => 'Ò¥', + 'Ò¦' => 'Ò§', + 'Ò¨' => 'Ò©', + 'Òª' => 'Ò«', + 'Ò¬' => 'Ò­', + 'Ò®' => 'Ò¯', + 'Ò°' => 'Ò±', + 'Ò²' => 'Ò³', + 'Ò´' => 'Òµ', + 'Ò¶' => 'Ò·', + 'Ò¸' => 'Ò¹', + 'Òº' => 'Ò»', + 'Ò¼' => 'Ò½', + 'Ò¾' => 'Ò¿', + 'Ó€' => 'Ó', + 'Ó' => 'Ó‚', + 'Óƒ' => 'Ó„', + 'Ó…' => 'Ó†', + 'Ó‡' => 'Óˆ', + 'Ó‰' => 'ÓŠ', + 'Ó‹' => 'ÓŒ', + 'Ó' => 'ÓŽ', + 'Ó' => 'Ó‘', + 'Ó’' => 'Ó“', + 'Ó”' => 'Ó•', + 'Ó–' => 'Ó—', + 'Ó˜' => 'Ó™', + 'Óš' => 'Ó›', + 'Óœ' => 'Ó', + 'Óž' => 'ÓŸ', + 'Ó ' => 'Ó¡', + 'Ó¢' => 'Ó£', + 'Ó¤' => 'Ó¥', + 'Ó¦' => 'Ó§', + 'Ó¨' => 'Ó©', + 'Óª' => 'Ó«', + 'Ó¬' => 'Ó­', + 'Ó®' => 'Ó¯', + 'Ó°' => 'Ó±', + 'Ó²' => 'Ó³', + 'Ó´' => 'Óµ', + 'Ó¶' => 'Ó·', + 'Ó¸' => 'Ó¹', + 'Óº' => 'Ó»', + 'Ó¼' => 'Ó½', + 'Ó¾' => 'Ó¿', + 'Ô€' => 'Ô', + 'Ô‚' => 'Ôƒ', + 'Ô„' => 'Ô…', + 'Ô†' => 'Ô‡', + 'Ôˆ' => 'Ô‰', + 'ÔŠ' => 'Ô‹', + 'ÔŒ' => 'Ô', + 'ÔŽ' => 'Ô', + 'Ô' => 'Ô‘', + 'Ô’' => 'Ô“', + 'Ô”' => 'Ô•', + 'Ô–' => 'Ô—', + 'Ô˜' => 'Ô™', + 'Ôš' => 'Ô›', + 'Ôœ' => 'Ô', + 'Ôž' => 'ÔŸ', + 'Ô ' => 'Ô¡', + 'Ô¢' => 'Ô£', + 'Ô¤' => 'Ô¥', + 'Ô¦' => 'Ô§', + 'Ô¨' => 'Ô©', + 'Ôª' => 'Ô«', + 'Ô¬' => 'Ô­', + 'Ô®' => 'Ô¯', + 'Ô±' => 'Õ¡', + 'Ô²' => 'Õ¢', + 'Ô³' => 'Õ£', + 'Ô´' => 'Õ¤', + 'Ôµ' => 'Õ¥', + 'Ô¶' => 'Õ¦', + 'Ô·' => 'Õ§', + 'Ô¸' => 'Õ¨', + 'Ô¹' => 'Õ©', + 'Ôº' => 'Õª', + 'Ô»' => 'Õ«', + 'Ô¼' => 'Õ¬', + 'Ô½' => 'Õ­', + 'Ô¾' => 'Õ®', + 'Ô¿' => 'Õ¯', + 'Õ€' => 'Õ°', + 'Õ' => 'Õ±', + 'Õ‚' => 'Õ²', + 'Õƒ' => 'Õ³', + 'Õ„' => 'Õ´', + 'Õ…' => 'Õµ', + 'Õ†' => 'Õ¶', + 'Õ‡' => 'Õ·', + 'Õˆ' => 'Õ¸', + 'Õ‰' => 'Õ¹', + 'ÕŠ' => 'Õº', + 'Õ‹' => 'Õ»', + 'ÕŒ' => 'Õ¼', + 'Õ' => 'Õ½', + 'ÕŽ' => 'Õ¾', + 'Õ' => 'Õ¿', + 'Õ' => 'Ö€', + 'Õ‘' => 'Ö', + 'Õ’' => 'Ö‚', + 'Õ“' => 'Öƒ', + 'Õ”' => 'Ö„', + 'Õ•' => 'Ö…', + 'Õ–' => 'Ö†', + 'á‚ ' => 'â´€', + 'á‚¡' => 'â´', + 'á‚¢' => 'â´‚', + 'á‚£' => 'â´ƒ', + 'Ⴄ' => 'â´„', + 'á‚¥' => 'â´…', + 'Ⴆ' => 'â´†', + 'á‚§' => 'â´‡', + 'Ⴈ' => 'â´ˆ', + 'á‚©' => 'â´‰', + 'Ⴊ' => 'â´Š', + 'á‚«' => 'â´‹', + 'Ⴌ' => 'â´Œ', + 'á‚­' => 'â´', + 'á‚®' => 'â´Ž', + 'Ⴏ' => 'â´', + 'á‚°' => 'â´', + 'Ⴑ' => 'â´‘', + 'Ⴒ' => 'â´’', + 'Ⴓ' => 'â´“', + 'á‚´' => 'â´”', + 'Ⴕ' => 'â´•', + 'á‚¶' => 'â´–', + 'á‚·' => 'â´—', + 'Ⴘ' => 'â´˜', + 'Ⴙ' => 'â´™', + 'Ⴚ' => 'â´š', + 'á‚»' => 'â´›', + 'Ⴜ' => 'â´œ', + 'Ⴝ' => 'â´', + 'Ⴞ' => 'â´ž', + 'á‚¿' => 'â´Ÿ', + 'Ⴠ' => 'â´ ', + 'áƒ' => 'â´¡', + 'Ⴢ' => 'â´¢', + 'Ⴣ' => 'â´£', + 'Ⴤ' => 'â´¤', + 'Ⴥ' => 'â´¥', + 'Ⴧ' => 'â´§', + 'áƒ' => 'â´­', + 'Ḁ' => 'á¸', + 'Ḃ' => 'ḃ', + 'Ḅ' => 'ḅ', + 'Ḇ' => 'ḇ', + 'Ḉ' => 'ḉ', + 'Ḋ' => 'ḋ', + 'Ḍ' => 'á¸', + 'Ḏ' => 'á¸', + 'á¸' => 'ḑ', + 'Ḓ' => 'ḓ', + 'Ḕ' => 'ḕ', + 'Ḗ' => 'ḗ', + 'Ḙ' => 'ḙ', + 'Ḛ' => 'ḛ', + 'Ḝ' => 'á¸', + 'Ḟ' => 'ḟ', + 'Ḡ' => 'ḡ', + 'Ḣ' => 'ḣ', + 'Ḥ' => 'ḥ', + 'Ḧ' => 'ḧ', + 'Ḩ' => 'ḩ', + 'Ḫ' => 'ḫ', + 'Ḭ' => 'ḭ', + 'Ḯ' => 'ḯ', + 'Ḱ' => 'ḱ', + 'Ḳ' => 'ḳ', + 'Ḵ' => 'ḵ', + 'Ḷ' => 'ḷ', + 'Ḹ' => 'ḹ', + 'Ḻ' => 'ḻ', + 'Ḽ' => 'ḽ', + 'Ḿ' => 'ḿ', + 'á¹€' => 'á¹', + 'Ṃ' => 'ṃ', + 'Ṅ' => 'á¹…', + 'Ṇ' => 'ṇ', + 'Ṉ' => 'ṉ', + 'Ṋ' => 'ṋ', + 'Ṍ' => 'á¹', + 'Ṏ' => 'á¹', + 'á¹' => 'ṑ', + 'á¹’' => 'ṓ', + 'á¹”' => 'ṕ', + 'á¹–' => 'á¹—', + 'Ṙ' => 'á¹™', + 'Ṛ' => 'á¹›', + 'Ṝ' => 'á¹', + 'Ṟ' => 'ṟ', + 'á¹ ' => 'ṡ', + 'á¹¢' => 'á¹£', + 'Ṥ' => 'á¹¥', + 'Ṧ' => 'á¹§', + 'Ṩ' => 'ṩ', + 'Ṫ' => 'ṫ', + 'Ṭ' => 'á¹­', + 'á¹®' => 'ṯ', + 'á¹°' => 'á¹±', + 'á¹²' => 'á¹³', + 'á¹´' => 'á¹µ', + 'á¹¶' => 'á¹·', + 'Ṹ' => 'á¹¹', + 'Ṻ' => 'á¹»', + 'á¹¼' => 'á¹½', + 'á¹¾' => 'ṿ', + 'Ẁ' => 'áº', + 'Ẃ' => 'ẃ', + 'Ẅ' => 'ẅ', + 'Ẇ' => 'ẇ', + 'Ẉ' => 'ẉ', + 'Ẋ' => 'ẋ', + 'Ẍ' => 'áº', + 'Ẏ' => 'áº', + 'áº' => 'ẑ', + 'Ẓ' => 'ẓ', + 'Ẕ' => 'ẕ', + 'ẞ' => 'ß', + 'Ạ' => 'ạ', + 'Ả' => 'ả', + 'Ấ' => 'ấ', + 'Ầ' => 'ầ', + 'Ẩ' => 'ẩ', + 'Ẫ' => 'ẫ', + 'Ậ' => 'ậ', + 'Ắ' => 'ắ', + 'Ằ' => 'ằ', + 'Ẳ' => 'ẳ', + 'Ẵ' => 'ẵ', + 'Ặ' => 'ặ', + 'Ẹ' => 'ẹ', + 'Ẻ' => 'ẻ', + 'Ẽ' => 'ẽ', + 'Ế' => 'ế', + 'Ề' => 'á»', + 'Ể' => 'ể', + 'Ễ' => 'á»…', + 'Ệ' => 'ệ', + 'Ỉ' => 'ỉ', + 'Ị' => 'ị', + 'Ọ' => 'á»', + 'Ỏ' => 'á»', + 'á»' => 'ố', + 'á»’' => 'ồ', + 'á»”' => 'ổ', + 'á»–' => 'á»—', + 'Ộ' => 'á»™', + 'Ớ' => 'á»›', + 'Ờ' => 'á»', + 'Ở' => 'ở', + 'á» ' => 'ỡ', + 'Ợ' => 'ợ', + 'Ụ' => 'ụ', + 'Ủ' => 'á»§', + 'Ứ' => 'ứ', + 'Ừ' => 'ừ', + 'Ử' => 'á»­', + 'á»®' => 'ữ', + 'á»°' => 'á»±', + 'Ỳ' => 'ỳ', + 'á»´' => 'ỵ', + 'á»¶' => 'á»·', + 'Ỹ' => 'ỹ', + 'Ỻ' => 'á»»', + 'Ỽ' => 'ỽ', + 'Ỿ' => 'ỿ', + 'Ἀ' => 'á¼€', + 'Ἁ' => 'á¼', + 'Ἂ' => 'ἂ', + 'Ἃ' => 'ἃ', + 'Ἄ' => 'ἄ', + 'á¼' => 'á¼…', + 'Ἆ' => 'ἆ', + 'á¼' => 'ἇ', + 'Ἐ' => 'á¼', + 'á¼™' => 'ἑ', + 'Ἒ' => 'á¼’', + 'á¼›' => 'ἓ', + 'Ἔ' => 'á¼”', + 'á¼' => 'ἕ', + 'Ἠ' => 'á¼ ', + 'Ἡ' => 'ἡ', + 'Ἢ' => 'á¼¢', + 'Ἣ' => 'á¼£', + 'Ἤ' => 'ἤ', + 'á¼­' => 'á¼¥', + 'á¼®' => 'ἦ', + 'Ἧ' => 'á¼§', + 'Ἰ' => 'á¼°', + 'á¼¹' => 'á¼±', + 'Ἲ' => 'á¼²', + 'á¼»' => 'á¼³', + 'á¼¼' => 'á¼´', + 'á¼½' => 'á¼µ', + 'á¼¾' => 'á¼¶', + 'Ἷ' => 'á¼·', + 'Ὀ' => 'á½€', + 'Ὁ' => 'á½', + 'Ὂ' => 'ὂ', + 'Ὃ' => 'ὃ', + 'Ὄ' => 'ὄ', + 'á½' => 'á½…', + 'á½™' => 'ὑ', + 'á½›' => 'ὓ', + 'á½' => 'ὕ', + 'Ὗ' => 'á½—', + 'Ὠ' => 'á½ ', + 'Ὡ' => 'ὡ', + 'Ὢ' => 'á½¢', + 'Ὣ' => 'á½£', + 'Ὤ' => 'ὤ', + 'á½­' => 'á½¥', + 'á½®' => 'ὦ', + 'Ὧ' => 'á½§', + 'ᾈ' => 'á¾€', + 'ᾉ' => 'á¾', + 'ᾊ' => 'ᾂ', + 'ᾋ' => 'ᾃ', + 'ᾌ' => 'ᾄ', + 'á¾' => 'á¾…', + 'ᾎ' => 'ᾆ', + 'á¾' => 'ᾇ', + 'ᾘ' => 'á¾', + 'á¾™' => 'ᾑ', + 'ᾚ' => 'á¾’', + 'á¾›' => 'ᾓ', + 'ᾜ' => 'á¾”', + 'á¾' => 'ᾕ', + 'ᾞ' => 'á¾–', + 'ᾟ' => 'á¾—', + 'ᾨ' => 'á¾ ', + 'ᾩ' => 'ᾡ', + 'ᾪ' => 'á¾¢', + 'ᾫ' => 'á¾£', + 'ᾬ' => 'ᾤ', + 'á¾­' => 'á¾¥', + 'á¾®' => 'ᾦ', + 'ᾯ' => 'á¾§', + 'Ᾰ' => 'á¾°', + 'á¾¹' => 'á¾±', + 'Ὰ' => 'á½°', + 'á¾»' => 'á½±', + 'á¾¼' => 'á¾³', + 'Ὲ' => 'á½²', + 'Έ' => 'á½³', + 'Ὴ' => 'á½´', + 'á¿‹' => 'á½µ', + 'ῌ' => 'ῃ', + 'Ῐ' => 'á¿', + 'á¿™' => 'á¿‘', + 'Ὶ' => 'á½¶', + 'á¿›' => 'á½·', + 'Ῠ' => 'á¿ ', + 'á¿©' => 'á¿¡', + 'Ὺ' => 'ὺ', + 'á¿«' => 'á½»', + 'Ῥ' => 'á¿¥', + 'Ὸ' => 'ὸ', + 'Ό' => 'á½¹', + 'Ὼ' => 'á½¼', + 'á¿»' => 'á½½', + 'ῼ' => 'ῳ', + 'Ω' => 'ω', + 'K' => 'k', + 'â„«' => 'Ã¥', + 'Ⅎ' => 'â…Ž', + 'â… ' => 'â…°', + 'â…¡' => 'â…±', + 'â…¢' => 'â…²', + 'â…£' => 'â…³', + 'â…¤' => 'â…´', + 'â…¥' => 'â…µ', + 'â…¦' => 'â…¶', + 'â…§' => 'â…·', + 'â…¨' => 'â…¸', + 'â…©' => 'â…¹', + 'â…ª' => 'â…º', + 'â…«' => 'â…»', + 'â…¬' => 'â…¼', + 'â…­' => 'â…½', + 'â…®' => 'â…¾', + 'â…¯' => 'â…¿', + 'Ↄ' => 'ↄ', + 'â’¶' => 'â“', + 'â’·' => 'â“‘', + 'â’¸' => 'â“’', + 'â’¹' => 'â““', + 'â’º' => 'â“”', + 'â’»' => 'â“•', + 'â’¼' => 'â“–', + 'â’½' => 'â“—', + 'â’¾' => 'ⓘ', + 'â’¿' => 'â“™', + 'â“€' => 'ⓚ', + 'â“' => 'â“›', + 'â“‚' => 'ⓜ', + 'Ⓝ' => 'â“', + 'â“„' => 'ⓞ', + 'â“…' => 'ⓟ', + 'Ⓠ' => 'â“ ', + 'Ⓡ' => 'â“¡', + 'Ⓢ' => 'â“¢', + 'Ⓣ' => 'â“£', + 'Ⓤ' => 'ⓤ', + 'â“‹' => 'â“¥', + 'Ⓦ' => 'ⓦ', + 'â“' => 'â“§', + 'Ⓨ' => 'ⓨ', + 'â“' => 'â“©', + 'â°€' => 'â°°', + 'â°' => 'â°±', + 'â°‚' => 'â°²', + 'â°ƒ' => 'â°³', + 'â°„' => 'â°´', + 'â°…' => 'â°µ', + 'â°†' => 'â°¶', + 'â°‡' => 'â°·', + 'â°ˆ' => 'â°¸', + 'â°‰' => 'â°¹', + 'â°Š' => 'â°º', + 'â°‹' => 'â°»', + 'â°Œ' => 'â°¼', + 'â°' => 'â°½', + 'â°Ž' => 'â°¾', + 'â°' => 'â°¿', + 'â°' => 'â±€', + 'â°‘' => 'â±', + 'â°’' => 'ⱂ', + 'â°“' => 'ⱃ', + 'â°”' => 'ⱄ', + 'â°•' => 'â±…', + 'â°–' => 'ⱆ', + 'â°—' => 'ⱇ', + 'â°˜' => 'ⱈ', + 'â°™' => 'ⱉ', + 'â°š' => 'ⱊ', + 'â°›' => 'ⱋ', + 'â°œ' => 'ⱌ', + 'â°' => 'â±', + 'â°ž' => 'ⱎ', + 'â°Ÿ' => 'â±', + 'â° ' => 'â±', + 'â°¡' => 'ⱑ', + 'â°¢' => 'â±’', + 'â°£' => 'ⱓ', + 'â°¤' => 'â±”', + 'â°¥' => 'ⱕ', + 'â°¦' => 'â±–', + 'â°§' => 'â±—', + 'â°¨' => 'ⱘ', + 'â°©' => 'â±™', + 'â°ª' => 'ⱚ', + 'â°«' => 'â±›', + 'â°¬' => 'ⱜ', + 'â°­' => 'â±', + 'â°®' => 'ⱞ', + 'â± ' => 'ⱡ', + 'â±¢' => 'É«', + 'â±£' => 'áµ½', + 'Ɽ' => 'ɽ', + 'â±§' => 'ⱨ', + 'Ⱪ' => 'ⱪ', + 'Ⱬ' => 'ⱬ', + 'â±­' => 'É‘', + 'â±®' => 'ɱ', + 'Ɐ' => 'É', + 'â±°' => 'É’', + 'â±²' => 'â±³', + 'â±µ' => 'â±¶', + 'â±¾' => 'È¿', + 'Ɀ' => 'É€', + 'â²€' => 'â²', + 'Ⲃ' => 'ⲃ', + 'Ⲅ' => 'â²…', + 'Ⲇ' => 'ⲇ', + 'Ⲉ' => 'ⲉ', + 'Ⲋ' => 'ⲋ', + 'Ⲍ' => 'â²', + 'Ⲏ' => 'â²', + 'â²' => 'ⲑ', + 'â²’' => 'ⲓ', + 'â²”' => 'ⲕ', + 'â²–' => 'â²—', + 'Ⲙ' => 'â²™', + 'Ⲛ' => 'â²›', + 'Ⲝ' => 'â²', + 'Ⲟ' => 'ⲟ', + 'â² ' => 'ⲡ', + 'â²¢' => 'â²£', + 'Ⲥ' => 'â²¥', + 'Ⲧ' => 'â²§', + 'Ⲩ' => 'ⲩ', + 'Ⲫ' => 'ⲫ', + 'Ⲭ' => 'â²­', + 'â²®' => 'ⲯ', + 'â²°' => 'â²±', + 'â²²' => 'â²³', + 'â²´' => 'â²µ', + 'â²¶' => 'â²·', + 'Ⲹ' => 'â²¹', + 'Ⲻ' => 'â²»', + 'â²¼' => 'â²½', + 'â²¾' => 'ⲿ', + 'â³€' => 'â³', + 'Ⳃ' => 'ⳃ', + 'Ⳅ' => 'â³…', + 'Ⳇ' => 'ⳇ', + 'Ⳉ' => 'ⳉ', + 'Ⳋ' => 'ⳋ', + 'Ⳍ' => 'â³', + 'Ⳏ' => 'â³', + 'â³' => 'ⳑ', + 'â³’' => 'ⳓ', + 'â³”' => 'ⳕ', + 'â³–' => 'â³—', + 'Ⳙ' => 'â³™', + 'Ⳛ' => 'â³›', + 'Ⳝ' => 'â³', + 'Ⳟ' => 'ⳟ', + 'â³ ' => 'ⳡ', + 'â³¢' => 'â³£', + 'Ⳬ' => 'ⳬ', + 'â³­' => 'â³®', + 'â³²' => 'â³³', + 'Ꙁ' => 'ê™', + 'Ꙃ' => 'ꙃ', + 'Ꙅ' => 'ê™…', + 'Ꙇ' => 'ꙇ', + 'Ꙉ' => 'ꙉ', + 'Ꙋ' => 'ꙋ', + 'Ꙍ' => 'ê™', + 'Ꙏ' => 'ê™', + 'ê™' => 'ꙑ', + 'ê™’' => 'ꙓ', + 'ê™”' => 'ꙕ', + 'ê™–' => 'ê™—', + 'Ꙙ' => 'ê™™', + 'Ꙛ' => 'ê™›', + 'Ꙝ' => 'ê™', + 'Ꙟ' => 'ꙟ', + 'ê™ ' => 'ꙡ', + 'Ꙣ' => 'ꙣ', + 'Ꙥ' => 'ꙥ', + 'Ꙧ' => 'ê™§', + 'Ꙩ' => 'ꙩ', + 'Ꙫ' => 'ꙫ', + 'Ꙭ' => 'ê™­', + 'Ꚁ' => 'êš', + 'êš‚' => 'ꚃ', + 'êš„' => 'êš…', + 'Ꚇ' => 'ꚇ', + 'Ꚉ' => 'ꚉ', + 'Ꚋ' => 'êš‹', + 'Ꚍ' => 'êš', + 'Ꚏ' => 'êš', + 'êš' => 'êš‘', + 'êš’' => 'êš“', + 'êš”' => 'êš•', + 'êš–' => 'êš—', + 'Ꚙ' => 'êš™', + 'êšš' => 'êš›', + 'Ꜣ' => 'ꜣ', + 'Ꜥ' => 'ꜥ', + 'Ꜧ' => 'ꜧ', + 'Ꜩ' => 'ꜩ', + 'Ꜫ' => 'ꜫ', + 'Ꜭ' => 'ꜭ', + 'Ꜯ' => 'ꜯ', + 'Ꜳ' => 'ꜳ', + 'Ꜵ' => 'ꜵ', + 'Ꜷ' => 'ꜷ', + 'Ꜹ' => 'ꜹ', + 'Ꜻ' => 'ꜻ', + 'Ꜽ' => 'ꜽ', + 'Ꜿ' => 'ꜿ', + 'ê€' => 'ê', + 'ê‚' => 'êƒ', + 'ê„' => 'ê…', + 'ê†' => 'ê‡', + 'êˆ' => 'ê‰', + 'êŠ' => 'ê‹', + 'êŒ' => 'ê', + 'êŽ' => 'ê', + 'ê' => 'ê‘', + 'ê’' => 'ê“', + 'ê”' => 'ê•', + 'ê–' => 'ê—', + 'ê˜' => 'ê™', + 'êš' => 'ê›', + 'êœ' => 'ê', + 'êž' => 'êŸ', + 'ê ' => 'ê¡', + 'ê¢' => 'ê£', + 'ê¤' => 'ê¥', + 'ê¦' => 'ê§', + 'ê¨' => 'ê©', + 'êª' => 'ê«', + 'ê¬' => 'ê­', + 'ê®' => 'ê¯', + 'ê¹' => 'êº', + 'ê»' => 'ê¼', + 'ê½' => 'áµ¹', + 'ê¾' => 'ê¿', + 'Ꞁ' => 'êž', + 'êž‚' => 'ꞃ', + 'êž„' => 'êž…', + 'Ꞇ' => 'ꞇ', + 'êž‹' => 'ꞌ', + 'êž' => 'É¥', + 'êž' => 'êž‘', + 'êž’' => 'êž“', + 'êž–' => 'êž—', + 'Ꞙ' => 'êž™', + 'êžš' => 'êž›', + 'êžœ' => 'êž', + 'êžž' => 'ꞟ', + 'êž ' => 'êž¡', + 'Ꞣ' => 'ꞣ', + 'Ꞥ' => 'ꞥ', + 'Ꞧ' => 'êž§', + 'Ꞩ' => 'êž©', + 'Ɦ' => 'ɦ', + 'êž«' => 'Éœ', + 'Ɡ' => 'É¡', + 'êž­' => 'ɬ', + 'êž°' => 'Êž', + 'êž±' => 'ʇ', + 'A' => 'ï½', + 'ï¼¢' => 'b', + 'ï¼£' => 'c', + 'D' => 'd', + 'ï¼¥' => 'ï½…', + 'F' => 'f', + 'ï¼§' => 'g', + 'H' => 'h', + 'I' => 'i', + 'J' => 'j', + 'K' => 'k', + 'L' => 'l', + 'ï¼­' => 'ï½', + 'ï¼®' => 'n', + 'O' => 'ï½', + 'ï¼°' => 'ï½', + 'ï¼±' => 'q', + 'ï¼²' => 'ï½’', + 'ï¼³' => 's', + 'ï¼´' => 'ï½”', + 'ï¼µ' => 'u', + 'ï¼¶' => 'ï½–', + 'ï¼·' => 'ï½—', + 'X' => 'x', + 'ï¼¹' => 'ï½™', + 'Z' => 'z', + 'ð€' => 'ð¨', + 'ð' => 'ð©', + 'ð‚' => 'ðª', + 'ðƒ' => 'ð«', + 'ð„' => 'ð¬', + 'ð…' => 'ð­', + 'ð†' => 'ð®', + 'ð‡' => 'ð¯', + 'ðˆ' => 'ð°', + 'ð‰' => 'ð±', + 'ðŠ' => 'ð²', + 'ð‹' => 'ð³', + 'ðŒ' => 'ð´', + 'ð' => 'ðµ', + 'ðŽ' => 'ð¶', + 'ð' => 'ð·', + 'ð' => 'ð¸', + 'ð‘' => 'ð¹', + 'ð’' => 'ðº', + 'ð“' => 'ð»', + 'ð”' => 'ð¼', + 'ð•' => 'ð½', + 'ð–' => 'ð¾', + 'ð—' => 'ð¿', + 'ð˜' => 'ð‘€', + 'ð™' => 'ð‘', + 'ðš' => 'ð‘‚', + 'ð›' => 'ð‘ƒ', + 'ðœ' => 'ð‘„', + 'ð' => 'ð‘…', + 'ðž' => 'ð‘†', + 'ðŸ' => 'ð‘‡', + 'ð ' => 'ð‘ˆ', + 'ð¡' => 'ð‘‰', + 'ð¢' => 'ð‘Š', + 'ð£' => 'ð‘‹', + 'ð¤' => 'ð‘Œ', + 'ð¥' => 'ð‘', + 'ð¦' => 'ð‘Ž', + 'ð§' => 'ð‘', + 'ð‘¢ ' => 'ð‘£€', + '𑢡' => 'ð‘£', + 'ð‘¢¢' => '𑣂', + 'ð‘¢£' => '𑣃', + '𑢤' => '𑣄', + 'ð‘¢¥' => 'ð‘£…', + '𑢦' => '𑣆', + 'ð‘¢§' => '𑣇', + '𑢨' => '𑣈', + '𑢩' => '𑣉', + '𑢪' => '𑣊', + '𑢫' => '𑣋', + '𑢬' => '𑣌', + 'ð‘¢­' => 'ð‘£', + 'ð‘¢®' => '𑣎', + '𑢯' => 'ð‘£', + 'ð‘¢°' => 'ð‘£', + 'ð‘¢±' => '𑣑', + 'ð‘¢²' => 'ð‘£’', + 'ð‘¢³' => '𑣓', + 'ð‘¢´' => 'ð‘£”', + 'ð‘¢µ' => '𑣕', + 'ð‘¢¶' => 'ð‘£–', + 'ð‘¢·' => 'ð‘£—', + '𑢸' => '𑣘', + 'ð‘¢¹' => 'ð‘£™', + '𑢺' => '𑣚', + 'ð‘¢»' => 'ð‘£›', + 'ð‘¢¼' => '𑣜', + 'ð‘¢½' => 'ð‘£', + 'ð‘¢¾' => '𑣞', + '𑢿' => '𑣟', +); diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php new file mode 100644 index 0000000..2a8f6e7 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php @@ -0,0 +1,5 @@ + 'A', + 'b' => 'B', + 'c' => 'C', + 'd' => 'D', + 'e' => 'E', + 'f' => 'F', + 'g' => 'G', + 'h' => 'H', + 'i' => 'I', + 'j' => 'J', + 'k' => 'K', + 'l' => 'L', + 'm' => 'M', + 'n' => 'N', + 'o' => 'O', + 'p' => 'P', + 'q' => 'Q', + 'r' => 'R', + 's' => 'S', + 't' => 'T', + 'u' => 'U', + 'v' => 'V', + 'w' => 'W', + 'x' => 'X', + 'y' => 'Y', + 'z' => 'Z', + 'µ' => 'Μ', + 'à' => 'À', + 'á' => 'Ã', + 'â' => 'Â', + 'ã' => 'Ã', + 'ä' => 'Ä', + 'Ã¥' => 'Ã…', + 'æ' => 'Æ', + 'ç' => 'Ç', + 'è' => 'È', + 'é' => 'É', + 'ê' => 'Ê', + 'ë' => 'Ë', + 'ì' => 'ÃŒ', + 'í' => 'Ã', + 'î' => 'ÃŽ', + 'ï' => 'Ã', + 'ð' => 'Ã', + 'ñ' => 'Ñ', + 'ò' => 'Ã’', + 'ó' => 'Ó', + 'ô' => 'Ô', + 'õ' => 'Õ', + 'ö' => 'Ö', + 'ø' => 'Ø', + 'ù' => 'Ù', + 'ú' => 'Ú', + 'û' => 'Û', + 'ü' => 'Ü', + 'ý' => 'Ã', + 'þ' => 'Þ', + 'ÿ' => 'Ÿ', + 'Ä' => 'Ä€', + 'ă' => 'Ä‚', + 'Ä…' => 'Ä„', + 'ć' => 'Ć', + 'ĉ' => 'Ĉ', + 'Ä‹' => 'ÄŠ', + 'Ä' => 'ÄŒ', + 'Ä' => 'ÄŽ', + 'Ä‘' => 'Ä', + 'Ä“' => 'Ä’', + 'Ä•' => 'Ä”', + 'Ä—' => 'Ä–', + 'Ä™' => 'Ę', + 'Ä›' => 'Äš', + 'Ä' => 'Äœ', + 'ÄŸ' => 'Äž', + 'Ä¡' => 'Ä ', + 'Ä£' => 'Ä¢', + 'Ä¥' => 'Ĥ', + 'ħ' => 'Ħ', + 'Ä©' => 'Ĩ', + 'Ä«' => 'Ī', + 'Ä­' => 'Ĭ', + 'į' => 'Ä®', + 'ı' => 'I', + 'ij' => 'IJ', + 'ĵ' => 'Ä´', + 'Ä·' => 'Ķ', + 'ĺ' => 'Ĺ', + 'ļ' => 'Ä»', + 'ľ' => 'Ľ', + 'Å€' => 'Ä¿', + 'Å‚' => 'Å', + 'Å„' => 'Ń', + 'ņ' => 'Å…', + 'ň' => 'Ň', + 'Å‹' => 'ÅŠ', + 'Å' => 'ÅŒ', + 'Å' => 'ÅŽ', + 'Å‘' => 'Å', + 'Å“' => 'Å’', + 'Å•' => 'Å”', + 'Å—' => 'Å–', + 'Å™' => 'Ř', + 'Å›' => 'Åš', + 'Å' => 'Åœ', + 'ÅŸ' => 'Åž', + 'Å¡' => 'Å ', + 'Å£' => 'Å¢', + 'Å¥' => 'Ť', + 'ŧ' => 'Ŧ', + 'Å©' => 'Ũ', + 'Å«' => 'Ū', + 'Å­' => 'Ŭ', + 'ů' => 'Å®', + 'ű' => 'Ű', + 'ų' => 'Ų', + 'ŵ' => 'Å´', + 'Å·' => 'Ŷ', + 'ź' => 'Ź', + 'ż' => 'Å»', + 'ž' => 'Ž', + 'Å¿' => 'S', + 'Æ€' => 'Ƀ', + 'ƃ' => 'Æ‚', + 'Æ…' => 'Æ„', + 'ƈ' => 'Ƈ', + 'ÆŒ' => 'Æ‹', + 'Æ’' => 'Æ‘', + 'Æ•' => 'Ƕ', + 'Æ™' => 'Ƙ', + 'Æš' => 'Ƚ', + 'Æž' => 'È ', + 'Æ¡' => 'Æ ', + 'Æ£' => 'Æ¢', + 'Æ¥' => 'Ƥ', + 'ƨ' => 'Ƨ', + 'Æ­' => 'Ƭ', + 'ư' => 'Ư', + 'Æ´' => 'Ƴ', + 'ƶ' => 'Ƶ', + 'ƹ' => 'Ƹ', + 'ƽ' => 'Ƽ', + 'Æ¿' => 'Ç·', + 'Ç…' => 'Ç„', + 'dž' => 'Ç„', + 'Lj' => 'LJ', + 'lj' => 'LJ', + 'Ç‹' => 'ÇŠ', + 'ÇŒ' => 'ÇŠ', + 'ÇŽ' => 'Ç', + 'Ç' => 'Ç', + 'Ç’' => 'Ç‘', + 'Ç”' => 'Ç“', + 'Ç–' => 'Ç•', + 'ǘ' => 'Ç—', + 'Çš' => 'Ç™', + 'Çœ' => 'Ç›', + 'Ç' => 'ÆŽ', + 'ÇŸ' => 'Çž', + 'Ç¡' => 'Ç ', + 'Ç£' => 'Ç¢', + 'Ç¥' => 'Ǥ', + 'ǧ' => 'Ǧ', + 'Ç©' => 'Ǩ', + 'Ç«' => 'Ǫ', + 'Ç­' => 'Ǭ', + 'ǯ' => 'Ç®', + 'Dz' => 'DZ', + 'dz' => 'DZ', + 'ǵ' => 'Ç´', + 'ǹ' => 'Ǹ', + 'Ç»' => 'Ǻ', + 'ǽ' => 'Ǽ', + 'Ç¿' => 'Ǿ', + 'È' => 'È€', + 'ȃ' => 'È‚', + 'È…' => 'È„', + 'ȇ' => 'Ȇ', + 'ȉ' => 'Ȉ', + 'È‹' => 'ÈŠ', + 'È' => 'ÈŒ', + 'È' => 'ÈŽ', + 'È‘' => 'È', + 'È“' => 'È’', + 'È•' => 'È”', + 'È—' => 'È–', + 'È™' => 'Ș', + 'È›' => 'Èš', + 'È' => 'Èœ', + 'ÈŸ' => 'Èž', + 'È£' => 'È¢', + 'È¥' => 'Ȥ', + 'ȧ' => 'Ȧ', + 'È©' => 'Ȩ', + 'È«' => 'Ȫ', + 'È­' => 'Ȭ', + 'ȯ' => 'È®', + 'ȱ' => 'Ȱ', + 'ȳ' => 'Ȳ', + 'ȼ' => 'È»', + 'È¿' => 'â±¾', + 'É€' => 'Ɀ', + 'É‚' => 'É', + 'ɇ' => 'Ɇ', + 'ɉ' => 'Ɉ', + 'É‹' => 'ÉŠ', + 'É' => 'ÉŒ', + 'É' => 'ÉŽ', + 'É' => 'Ɐ', + 'É‘' => 'â±­', + 'É’' => 'â±°', + 'É“' => 'Æ', + 'É”' => 'Ɔ', + 'É–' => 'Ɖ', + 'É—' => 'ÆŠ', + 'É™' => 'Æ', + 'É›' => 'Æ', + 'Éœ' => 'êž«', + 'É ' => 'Æ“', + 'É¡' => 'Ɡ', + 'É£' => 'Æ”', + 'É¥' => 'êž', + 'ɦ' => 'Ɦ', + 'ɨ' => 'Æ—', + 'É©' => 'Æ–', + 'É«' => 'â±¢', + 'ɬ' => 'êž­', + 'ɯ' => 'Æœ', + 'ɱ' => 'â±®', + 'ɲ' => 'Æ', + 'ɵ' => 'ÆŸ', + 'ɽ' => 'Ɽ', + 'Ê€' => 'Ʀ', + 'ʃ' => 'Æ©', + 'ʇ' => 'êž±', + 'ʈ' => 'Æ®', + 'ʉ' => 'É„', + 'ÊŠ' => 'Ʊ', + 'Ê‹' => 'Ʋ', + 'ÊŒ' => 'É…', + 'Ê’' => 'Æ·', + 'Êž' => 'êž°', + 'Í…' => 'Ι', + 'ͱ' => 'Ͱ', + 'ͳ' => 'Ͳ', + 'Í·' => 'Ͷ', + 'Í»' => 'Ͻ', + 'ͼ' => 'Ͼ', + 'ͽ' => 'Ï¿', + 'ά' => 'Ά', + 'έ' => 'Έ', + 'ή' => 'Ή', + 'ί' => 'Ί', + 'α' => 'Α', + 'β' => 'Î’', + 'γ' => 'Γ', + 'δ' => 'Δ', + 'ε' => 'Ε', + 'ζ' => 'Ζ', + 'η' => 'Η', + 'θ' => 'Θ', + 'ι' => 'Ι', + 'κ' => 'Κ', + 'λ' => 'Λ', + 'μ' => 'Μ', + 'ν' => 'Î', + 'ξ' => 'Ξ', + 'ο' => 'Ο', + 'Ï€' => 'Π', + 'Ï' => 'Ρ', + 'Ï‚' => 'Σ', + 'σ' => 'Σ', + 'Ï„' => 'Τ', + 'Ï…' => 'Î¥', + 'φ' => 'Φ', + 'χ' => 'Χ', + 'ψ' => 'Ψ', + 'ω' => 'Ω', + 'ÏŠ' => 'Ϊ', + 'Ï‹' => 'Ϋ', + 'ÏŒ' => 'ÎŒ', + 'Ï' => 'ÎŽ', + 'ÏŽ' => 'Î', + 'Ï' => 'Î’', + 'Ï‘' => 'Θ', + 'Ï•' => 'Φ', + 'Ï–' => 'Π', + 'Ï—' => 'Ï', + 'Ï™' => 'Ϙ', + 'Ï›' => 'Ïš', + 'Ï' => 'Ïœ', + 'ÏŸ' => 'Ïž', + 'Ï¡' => 'Ï ', + 'Ï£' => 'Ï¢', + 'Ï¥' => 'Ϥ', + 'ϧ' => 'Ϧ', + 'Ï©' => 'Ϩ', + 'Ï«' => 'Ϫ', + 'Ï­' => 'Ϭ', + 'ϯ' => 'Ï®', + 'ϰ' => 'Κ', + 'ϱ' => 'Ρ', + 'ϲ' => 'Ϲ', + 'ϳ' => 'Í¿', + 'ϵ' => 'Ε', + 'ϸ' => 'Ï·', + 'Ï»' => 'Ϻ', + 'а' => 'Ð', + 'б' => 'Б', + 'в' => 'Ð’', + 'г' => 'Г', + 'д' => 'Д', + 'е' => 'Е', + 'ж' => 'Ж', + 'з' => 'З', + 'и' => 'И', + 'й' => 'Й', + 'к' => 'К', + 'л' => 'Л', + 'м' => 'М', + 'н' => 'Ð', + 'о' => 'О', + 'п' => 'П', + 'Ñ€' => 'Р', + 'Ñ' => 'С', + 'Ñ‚' => 'Т', + 'у' => 'У', + 'Ñ„' => 'Ф', + 'Ñ…' => 'Ð¥', + 'ц' => 'Ц', + 'ч' => 'Ч', + 'ш' => 'Ш', + 'щ' => 'Щ', + 'ÑŠ' => 'Ъ', + 'Ñ‹' => 'Ы', + 'ÑŒ' => 'Ь', + 'Ñ' => 'Э', + 'ÑŽ' => 'Ю', + 'Ñ' => 'Я', + 'Ñ' => 'Ѐ', + 'Ñ‘' => 'Ð', + 'Ñ’' => 'Ђ', + 'Ñ“' => 'Ѓ', + 'Ñ”' => 'Є', + 'Ñ•' => 'Ð…', + 'Ñ–' => 'І', + 'Ñ—' => 'Ї', + 'ј' => 'Ј', + 'Ñ™' => 'Љ', + 'Ñš' => 'Њ', + 'Ñ›' => 'Ћ', + 'Ñœ' => 'ÐŒ', + 'Ñ' => 'Ð', + 'Ñž' => 'ÐŽ', + 'ÑŸ' => 'Ð', + 'Ñ¡' => 'Ñ ', + 'Ñ£' => 'Ñ¢', + 'Ñ¥' => 'Ѥ', + 'ѧ' => 'Ѧ', + 'Ñ©' => 'Ѩ', + 'Ñ«' => 'Ѫ', + 'Ñ­' => 'Ѭ', + 'ѯ' => 'Ñ®', + 'ѱ' => 'Ѱ', + 'ѳ' => 'Ѳ', + 'ѵ' => 'Ñ´', + 'Ñ·' => 'Ѷ', + 'ѹ' => 'Ѹ', + 'Ñ»' => 'Ѻ', + 'ѽ' => 'Ѽ', + 'Ñ¿' => 'Ѿ', + 'Ò' => 'Ò€', + 'Ò‹' => 'ÒŠ', + 'Ò' => 'ÒŒ', + 'Ò' => 'ÒŽ', + 'Ò‘' => 'Ò', + 'Ò“' => 'Ò’', + 'Ò•' => 'Ò”', + 'Ò—' => 'Ò–', + 'Ò™' => 'Ò˜', + 'Ò›' => 'Òš', + 'Ò' => 'Òœ', + 'ÒŸ' => 'Òž', + 'Ò¡' => 'Ò ', + 'Ò£' => 'Ò¢', + 'Ò¥' => 'Ò¤', + 'Ò§' => 'Ò¦', + 'Ò©' => 'Ò¨', + 'Ò«' => 'Òª', + 'Ò­' => 'Ò¬', + 'Ò¯' => 'Ò®', + 'Ò±' => 'Ò°', + 'Ò³' => 'Ò²', + 'Òµ' => 'Ò´', + 'Ò·' => 'Ò¶', + 'Ò¹' => 'Ò¸', + 'Ò»' => 'Òº', + 'Ò½' => 'Ò¼', + 'Ò¿' => 'Ò¾', + 'Ó‚' => 'Ó', + 'Ó„' => 'Óƒ', + 'Ó†' => 'Ó…', + 'Óˆ' => 'Ó‡', + 'ÓŠ' => 'Ó‰', + 'ÓŒ' => 'Ó‹', + 'ÓŽ' => 'Ó', + 'Ó' => 'Ó€', + 'Ó‘' => 'Ó', + 'Ó“' => 'Ó’', + 'Ó•' => 'Ó”', + 'Ó—' => 'Ó–', + 'Ó™' => 'Ó˜', + 'Ó›' => 'Óš', + 'Ó' => 'Óœ', + 'ÓŸ' => 'Óž', + 'Ó¡' => 'Ó ', + 'Ó£' => 'Ó¢', + 'Ó¥' => 'Ó¤', + 'Ó§' => 'Ó¦', + 'Ó©' => 'Ó¨', + 'Ó«' => 'Óª', + 'Ó­' => 'Ó¬', + 'Ó¯' => 'Ó®', + 'Ó±' => 'Ó°', + 'Ó³' => 'Ó²', + 'Óµ' => 'Ó´', + 'Ó·' => 'Ó¶', + 'Ó¹' => 'Ó¸', + 'Ó»' => 'Óº', + 'Ó½' => 'Ó¼', + 'Ó¿' => 'Ó¾', + 'Ô' => 'Ô€', + 'Ôƒ' => 'Ô‚', + 'Ô…' => 'Ô„', + 'Ô‡' => 'Ô†', + 'Ô‰' => 'Ôˆ', + 'Ô‹' => 'ÔŠ', + 'Ô' => 'ÔŒ', + 'Ô' => 'ÔŽ', + 'Ô‘' => 'Ô', + 'Ô“' => 'Ô’', + 'Ô•' => 'Ô”', + 'Ô—' => 'Ô–', + 'Ô™' => 'Ô˜', + 'Ô›' => 'Ôš', + 'Ô' => 'Ôœ', + 'ÔŸ' => 'Ôž', + 'Ô¡' => 'Ô ', + 'Ô£' => 'Ô¢', + 'Ô¥' => 'Ô¤', + 'Ô§' => 'Ô¦', + 'Ô©' => 'Ô¨', + 'Ô«' => 'Ôª', + 'Ô­' => 'Ô¬', + 'Ô¯' => 'Ô®', + 'Õ¡' => 'Ô±', + 'Õ¢' => 'Ô²', + 'Õ£' => 'Ô³', + 'Õ¤' => 'Ô´', + 'Õ¥' => 'Ôµ', + 'Õ¦' => 'Ô¶', + 'Õ§' => 'Ô·', + 'Õ¨' => 'Ô¸', + 'Õ©' => 'Ô¹', + 'Õª' => 'Ôº', + 'Õ«' => 'Ô»', + 'Õ¬' => 'Ô¼', + 'Õ­' => 'Ô½', + 'Õ®' => 'Ô¾', + 'Õ¯' => 'Ô¿', + 'Õ°' => 'Õ€', + 'Õ±' => 'Õ', + 'Õ²' => 'Õ‚', + 'Õ³' => 'Õƒ', + 'Õ´' => 'Õ„', + 'Õµ' => 'Õ…', + 'Õ¶' => 'Õ†', + 'Õ·' => 'Õ‡', + 'Õ¸' => 'Õˆ', + 'Õ¹' => 'Õ‰', + 'Õº' => 'ÕŠ', + 'Õ»' => 'Õ‹', + 'Õ¼' => 'ÕŒ', + 'Õ½' => 'Õ', + 'Õ¾' => 'ÕŽ', + 'Õ¿' => 'Õ', + 'Ö€' => 'Õ', + 'Ö' => 'Õ‘', + 'Ö‚' => 'Õ’', + 'Öƒ' => 'Õ“', + 'Ö„' => 'Õ”', + 'Ö…' => 'Õ•', + 'Ö†' => 'Õ–', + 'áµ¹' => 'ê½', + 'áµ½' => 'â±£', + 'á¸' => 'Ḁ', + 'ḃ' => 'Ḃ', + 'ḅ' => 'Ḅ', + 'ḇ' => 'Ḇ', + 'ḉ' => 'Ḉ', + 'ḋ' => 'Ḋ', + 'á¸' => 'Ḍ', + 'á¸' => 'Ḏ', + 'ḑ' => 'á¸', + 'ḓ' => 'Ḓ', + 'ḕ' => 'Ḕ', + 'ḗ' => 'Ḗ', + 'ḙ' => 'Ḙ', + 'ḛ' => 'Ḛ', + 'á¸' => 'Ḝ', + 'ḟ' => 'Ḟ', + 'ḡ' => 'Ḡ', + 'ḣ' => 'Ḣ', + 'ḥ' => 'Ḥ', + 'ḧ' => 'Ḧ', + 'ḩ' => 'Ḩ', + 'ḫ' => 'Ḫ', + 'ḭ' => 'Ḭ', + 'ḯ' => 'Ḯ', + 'ḱ' => 'Ḱ', + 'ḳ' => 'Ḳ', + 'ḵ' => 'Ḵ', + 'ḷ' => 'Ḷ', + 'ḹ' => 'Ḹ', + 'ḻ' => 'Ḻ', + 'ḽ' => 'Ḽ', + 'ḿ' => 'Ḿ', + 'á¹' => 'á¹€', + 'ṃ' => 'Ṃ', + 'á¹…' => 'Ṅ', + 'ṇ' => 'Ṇ', + 'ṉ' => 'Ṉ', + 'ṋ' => 'Ṋ', + 'á¹' => 'Ṍ', + 'á¹' => 'Ṏ', + 'ṑ' => 'á¹', + 'ṓ' => 'á¹’', + 'ṕ' => 'á¹”', + 'á¹—' => 'á¹–', + 'á¹™' => 'Ṙ', + 'á¹›' => 'Ṛ', + 'á¹' => 'Ṝ', + 'ṟ' => 'Ṟ', + 'ṡ' => 'á¹ ', + 'á¹£' => 'á¹¢', + 'á¹¥' => 'Ṥ', + 'á¹§' => 'Ṧ', + 'ṩ' => 'Ṩ', + 'ṫ' => 'Ṫ', + 'á¹­' => 'Ṭ', + 'ṯ' => 'á¹®', + 'á¹±' => 'á¹°', + 'á¹³' => 'á¹²', + 'á¹µ' => 'á¹´', + 'á¹·' => 'á¹¶', + 'á¹¹' => 'Ṹ', + 'á¹»' => 'Ṻ', + 'á¹½' => 'á¹¼', + 'ṿ' => 'á¹¾', + 'áº' => 'Ẁ', + 'ẃ' => 'Ẃ', + 'ẅ' => 'Ẅ', + 'ẇ' => 'Ẇ', + 'ẉ' => 'Ẉ', + 'ẋ' => 'Ẋ', + 'áº' => 'Ẍ', + 'áº' => 'Ẏ', + 'ẑ' => 'áº', + 'ẓ' => 'Ẓ', + 'ẕ' => 'Ẕ', + 'ẛ' => 'á¹ ', + 'ạ' => 'Ạ', + 'ả' => 'Ả', + 'ấ' => 'Ấ', + 'ầ' => 'Ầ', + 'ẩ' => 'Ẩ', + 'ẫ' => 'Ẫ', + 'ậ' => 'Ậ', + 'ắ' => 'Ắ', + 'ằ' => 'Ằ', + 'ẳ' => 'Ẳ', + 'ẵ' => 'Ẵ', + 'ặ' => 'Ặ', + 'ẹ' => 'Ẹ', + 'ẻ' => 'Ẻ', + 'ẽ' => 'Ẽ', + 'ế' => 'Ế', + 'á»' => 'Ề', + 'ể' => 'Ể', + 'á»…' => 'Ễ', + 'ệ' => 'Ệ', + 'ỉ' => 'Ỉ', + 'ị' => 'Ị', + 'á»' => 'Ọ', + 'á»' => 'Ỏ', + 'ố' => 'á»', + 'ồ' => 'á»’', + 'ổ' => 'á»”', + 'á»—' => 'á»–', + 'á»™' => 'Ộ', + 'á»›' => 'Ớ', + 'á»' => 'Ờ', + 'ở' => 'Ở', + 'ỡ' => 'á» ', + 'ợ' => 'Ợ', + 'ụ' => 'Ụ', + 'á»§' => 'Ủ', + 'ứ' => 'Ứ', + 'ừ' => 'Ừ', + 'á»­' => 'Ử', + 'ữ' => 'á»®', + 'á»±' => 'á»°', + 'ỳ' => 'Ỳ', + 'ỵ' => 'á»´', + 'á»·' => 'á»¶', + 'ỹ' => 'Ỹ', + 'á»»' => 'Ỻ', + 'ỽ' => 'Ỽ', + 'ỿ' => 'Ỿ', + 'á¼€' => 'Ἀ', + 'á¼' => 'Ἁ', + 'ἂ' => 'Ἂ', + 'ἃ' => 'Ἃ', + 'ἄ' => 'Ἄ', + 'á¼…' => 'á¼', + 'ἆ' => 'Ἆ', + 'ἇ' => 'á¼', + 'á¼' => 'Ἐ', + 'ἑ' => 'á¼™', + 'á¼’' => 'Ἒ', + 'ἓ' => 'á¼›', + 'á¼”' => 'Ἔ', + 'ἕ' => 'á¼', + 'á¼ ' => 'Ἠ', + 'ἡ' => 'Ἡ', + 'á¼¢' => 'Ἢ', + 'á¼£' => 'Ἣ', + 'ἤ' => 'Ἤ', + 'á¼¥' => 'á¼­', + 'ἦ' => 'á¼®', + 'á¼§' => 'Ἧ', + 'á¼°' => 'Ἰ', + 'á¼±' => 'á¼¹', + 'á¼²' => 'Ἲ', + 'á¼³' => 'á¼»', + 'á¼´' => 'á¼¼', + 'á¼µ' => 'á¼½', + 'á¼¶' => 'á¼¾', + 'á¼·' => 'Ἷ', + 'á½€' => 'Ὀ', + 'á½' => 'Ὁ', + 'ὂ' => 'Ὂ', + 'ὃ' => 'Ὃ', + 'ὄ' => 'Ὄ', + 'á½…' => 'á½', + 'ὑ' => 'á½™', + 'ὓ' => 'á½›', + 'ὕ' => 'á½', + 'á½—' => 'Ὗ', + 'á½ ' => 'Ὠ', + 'ὡ' => 'Ὡ', + 'á½¢' => 'Ὢ', + 'á½£' => 'Ὣ', + 'ὤ' => 'Ὤ', + 'á½¥' => 'á½­', + 'ὦ' => 'á½®', + 'á½§' => 'Ὧ', + 'á½°' => 'Ὰ', + 'á½±' => 'á¾»', + 'á½²' => 'Ὲ', + 'á½³' => 'Έ', + 'á½´' => 'Ὴ', + 'á½µ' => 'á¿‹', + 'á½¶' => 'Ὶ', + 'á½·' => 'á¿›', + 'ὸ' => 'Ὸ', + 'á½¹' => 'Ό', + 'ὺ' => 'Ὺ', + 'á½»' => 'á¿«', + 'á½¼' => 'Ὼ', + 'á½½' => 'á¿»', + 'á¾€' => 'ᾈ', + 'á¾' => 'ᾉ', + 'ᾂ' => 'ᾊ', + 'ᾃ' => 'ᾋ', + 'ᾄ' => 'ᾌ', + 'á¾…' => 'á¾', + 'ᾆ' => 'ᾎ', + 'ᾇ' => 'á¾', + 'á¾' => 'ᾘ', + 'ᾑ' => 'á¾™', + 'á¾’' => 'ᾚ', + 'ᾓ' => 'á¾›', + 'á¾”' => 'ᾜ', + 'ᾕ' => 'á¾', + 'á¾–' => 'ᾞ', + 'á¾—' => 'ᾟ', + 'á¾ ' => 'ᾨ', + 'ᾡ' => 'ᾩ', + 'á¾¢' => 'ᾪ', + 'á¾£' => 'ᾫ', + 'ᾤ' => 'ᾬ', + 'á¾¥' => 'á¾­', + 'ᾦ' => 'á¾®', + 'á¾§' => 'ᾯ', + 'á¾°' => 'Ᾰ', + 'á¾±' => 'á¾¹', + 'á¾³' => 'á¾¼', + 'á¾¾' => 'Ι', + 'ῃ' => 'ῌ', + 'á¿' => 'Ῐ', + 'á¿‘' => 'á¿™', + 'á¿ ' => 'Ῠ', + 'á¿¡' => 'á¿©', + 'á¿¥' => 'Ῥ', + 'ῳ' => 'ῼ', + 'â…Ž' => 'Ⅎ', + 'â…°' => 'â… ', + 'â…±' => 'â…¡', + 'â…²' => 'â…¢', + 'â…³' => 'â…£', + 'â…´' => 'â…¤', + 'â…µ' => 'â…¥', + 'â…¶' => 'â…¦', + 'â…·' => 'â…§', + 'â…¸' => 'â…¨', + 'â…¹' => 'â…©', + 'â…º' => 'â…ª', + 'â…»' => 'â…«', + 'â…¼' => 'â…¬', + 'â…½' => 'â…­', + 'â…¾' => 'â…®', + 'â…¿' => 'â…¯', + 'ↄ' => 'Ↄ', + 'â“' => 'â’¶', + 'â“‘' => 'â’·', + 'â“’' => 'â’¸', + 'â““' => 'â’¹', + 'â“”' => 'â’º', + 'â“•' => 'â’»', + 'â“–' => 'â’¼', + 'â“—' => 'â’½', + 'ⓘ' => 'â’¾', + 'â“™' => 'â’¿', + 'ⓚ' => 'â“€', + 'â“›' => 'â“', + 'ⓜ' => 'â“‚', + 'â“' => 'Ⓝ', + 'ⓞ' => 'â“„', + 'ⓟ' => 'â“…', + 'â“ ' => 'Ⓠ', + 'â“¡' => 'Ⓡ', + 'â“¢' => 'Ⓢ', + 'â“£' => 'Ⓣ', + 'ⓤ' => 'Ⓤ', + 'â“¥' => 'â“‹', + 'ⓦ' => 'Ⓦ', + 'â“§' => 'â“', + 'ⓨ' => 'Ⓨ', + 'â“©' => 'â“', + 'â°°' => 'â°€', + 'â°±' => 'â°', + 'â°²' => 'â°‚', + 'â°³' => 'â°ƒ', + 'â°´' => 'â°„', + 'â°µ' => 'â°…', + 'â°¶' => 'â°†', + 'â°·' => 'â°‡', + 'â°¸' => 'â°ˆ', + 'â°¹' => 'â°‰', + 'â°º' => 'â°Š', + 'â°»' => 'â°‹', + 'â°¼' => 'â°Œ', + 'â°½' => 'â°', + 'â°¾' => 'â°Ž', + 'â°¿' => 'â°', + 'â±€' => 'â°', + 'â±' => 'â°‘', + 'ⱂ' => 'â°’', + 'ⱃ' => 'â°“', + 'ⱄ' => 'â°”', + 'â±…' => 'â°•', + 'ⱆ' => 'â°–', + 'ⱇ' => 'â°—', + 'ⱈ' => 'â°˜', + 'ⱉ' => 'â°™', + 'ⱊ' => 'â°š', + 'ⱋ' => 'â°›', + 'ⱌ' => 'â°œ', + 'â±' => 'â°', + 'ⱎ' => 'â°ž', + 'â±' => 'â°Ÿ', + 'â±' => 'â° ', + 'ⱑ' => 'â°¡', + 'â±’' => 'â°¢', + 'ⱓ' => 'â°£', + 'â±”' => 'â°¤', + 'ⱕ' => 'â°¥', + 'â±–' => 'â°¦', + 'â±—' => 'â°§', + 'ⱘ' => 'â°¨', + 'â±™' => 'â°©', + 'ⱚ' => 'â°ª', + 'â±›' => 'â°«', + 'ⱜ' => 'â°¬', + 'â±' => 'â°­', + 'ⱞ' => 'â°®', + 'ⱡ' => 'â± ', + 'â±¥' => 'Ⱥ', + 'ⱦ' => 'Ⱦ', + 'ⱨ' => 'â±§', + 'ⱪ' => 'Ⱪ', + 'ⱬ' => 'Ⱬ', + 'â±³' => 'â±²', + 'â±¶' => 'â±µ', + 'â²' => 'â²€', + 'ⲃ' => 'Ⲃ', + 'â²…' => 'Ⲅ', + 'ⲇ' => 'Ⲇ', + 'ⲉ' => 'Ⲉ', + 'ⲋ' => 'Ⲋ', + 'â²' => 'Ⲍ', + 'â²' => 'Ⲏ', + 'ⲑ' => 'â²', + 'ⲓ' => 'â²’', + 'ⲕ' => 'â²”', + 'â²—' => 'â²–', + 'â²™' => 'Ⲙ', + 'â²›' => 'Ⲛ', + 'â²' => 'Ⲝ', + 'ⲟ' => 'Ⲟ', + 'ⲡ' => 'â² ', + 'â²£' => 'â²¢', + 'â²¥' => 'Ⲥ', + 'â²§' => 'Ⲧ', + 'ⲩ' => 'Ⲩ', + 'ⲫ' => 'Ⲫ', + 'â²­' => 'Ⲭ', + 'ⲯ' => 'â²®', + 'â²±' => 'â²°', + 'â²³' => 'â²²', + 'â²µ' => 'â²´', + 'â²·' => 'â²¶', + 'â²¹' => 'Ⲹ', + 'â²»' => 'Ⲻ', + 'â²½' => 'â²¼', + 'ⲿ' => 'â²¾', + 'â³' => 'â³€', + 'ⳃ' => 'Ⳃ', + 'â³…' => 'Ⳅ', + 'ⳇ' => 'Ⳇ', + 'ⳉ' => 'Ⳉ', + 'ⳋ' => 'Ⳋ', + 'â³' => 'Ⳍ', + 'â³' => 'Ⳏ', + 'ⳑ' => 'â³', + 'ⳓ' => 'â³’', + 'ⳕ' => 'â³”', + 'â³—' => 'â³–', + 'â³™' => 'Ⳙ', + 'â³›' => 'Ⳛ', + 'â³' => 'Ⳝ', + 'ⳟ' => 'Ⳟ', + 'ⳡ' => 'â³ ', + 'â³£' => 'â³¢', + 'ⳬ' => 'Ⳬ', + 'â³®' => 'â³­', + 'â³³' => 'â³²', + 'â´€' => 'á‚ ', + 'â´' => 'á‚¡', + 'â´‚' => 'á‚¢', + 'â´ƒ' => 'á‚£', + 'â´„' => 'Ⴄ', + 'â´…' => 'á‚¥', + 'â´†' => 'Ⴆ', + 'â´‡' => 'á‚§', + 'â´ˆ' => 'Ⴈ', + 'â´‰' => 'á‚©', + 'â´Š' => 'Ⴊ', + 'â´‹' => 'á‚«', + 'â´Œ' => 'Ⴌ', + 'â´' => 'á‚­', + 'â´Ž' => 'á‚®', + 'â´' => 'Ⴏ', + 'â´' => 'á‚°', + 'â´‘' => 'Ⴑ', + 'â´’' => 'Ⴒ', + 'â´“' => 'Ⴓ', + 'â´”' => 'á‚´', + 'â´•' => 'Ⴕ', + 'â´–' => 'á‚¶', + 'â´—' => 'á‚·', + 'â´˜' => 'Ⴘ', + 'â´™' => 'Ⴙ', + 'â´š' => 'Ⴚ', + 'â´›' => 'á‚»', + 'â´œ' => 'Ⴜ', + 'â´' => 'Ⴝ', + 'â´ž' => 'Ⴞ', + 'â´Ÿ' => 'á‚¿', + 'â´ ' => 'Ⴠ', + 'â´¡' => 'áƒ', + 'â´¢' => 'Ⴢ', + 'â´£' => 'Ⴣ', + 'â´¤' => 'Ⴤ', + 'â´¥' => 'Ⴥ', + 'â´§' => 'Ⴧ', + 'â´­' => 'áƒ', + 'ê™' => 'Ꙁ', + 'ꙃ' => 'Ꙃ', + 'ê™…' => 'Ꙅ', + 'ꙇ' => 'Ꙇ', + 'ꙉ' => 'Ꙉ', + 'ꙋ' => 'Ꙋ', + 'ê™' => 'Ꙍ', + 'ê™' => 'Ꙏ', + 'ꙑ' => 'ê™', + 'ꙓ' => 'ê™’', + 'ꙕ' => 'ê™”', + 'ê™—' => 'ê™–', + 'ê™™' => 'Ꙙ', + 'ê™›' => 'Ꙛ', + 'ê™' => 'Ꙝ', + 'ꙟ' => 'Ꙟ', + 'ꙡ' => 'ê™ ', + 'ꙣ' => 'Ꙣ', + 'ꙥ' => 'Ꙥ', + 'ê™§' => 'Ꙧ', + 'ꙩ' => 'Ꙩ', + 'ꙫ' => 'Ꙫ', + 'ê™­' => 'Ꙭ', + 'êš' => 'Ꚁ', + 'ꚃ' => 'êš‚', + 'êš…' => 'êš„', + 'ꚇ' => 'Ꚇ', + 'ꚉ' => 'Ꚉ', + 'êš‹' => 'Ꚋ', + 'êš' => 'Ꚍ', + 'êš' => 'Ꚏ', + 'êš‘' => 'êš', + 'êš“' => 'êš’', + 'êš•' => 'êš”', + 'êš—' => 'êš–', + 'êš™' => 'Ꚙ', + 'êš›' => 'êšš', + 'ꜣ' => 'Ꜣ', + 'ꜥ' => 'Ꜥ', + 'ꜧ' => 'Ꜧ', + 'ꜩ' => 'Ꜩ', + 'ꜫ' => 'Ꜫ', + 'ꜭ' => 'Ꜭ', + 'ꜯ' => 'Ꜯ', + 'ꜳ' => 'Ꜳ', + 'ꜵ' => 'Ꜵ', + 'ꜷ' => 'Ꜷ', + 'ꜹ' => 'Ꜹ', + 'ꜻ' => 'Ꜻ', + 'ꜽ' => 'Ꜽ', + 'ꜿ' => 'Ꜿ', + 'ê' => 'ê€', + 'êƒ' => 'ê‚', + 'ê…' => 'ê„', + 'ê‡' => 'ê†', + 'ê‰' => 'êˆ', + 'ê‹' => 'êŠ', + 'ê' => 'êŒ', + 'ê' => 'êŽ', + 'ê‘' => 'ê', + 'ê“' => 'ê’', + 'ê•' => 'ê”', + 'ê—' => 'ê–', + 'ê™' => 'ê˜', + 'ê›' => 'êš', + 'ê' => 'êœ', + 'êŸ' => 'êž', + 'ê¡' => 'ê ', + 'ê£' => 'ê¢', + 'ê¥' => 'ê¤', + 'ê§' => 'ê¦', + 'ê©' => 'ê¨', + 'ê«' => 'êª', + 'ê­' => 'ê¬', + 'ê¯' => 'ê®', + 'êº' => 'ê¹', + 'ê¼' => 'ê»', + 'ê¿' => 'ê¾', + 'êž' => 'Ꞁ', + 'ꞃ' => 'êž‚', + 'êž…' => 'êž„', + 'ꞇ' => 'Ꞇ', + 'ꞌ' => 'êž‹', + 'êž‘' => 'êž', + 'êž“' => 'êž’', + 'êž—' => 'êž–', + 'êž™' => 'Ꞙ', + 'êž›' => 'êžš', + 'êž' => 'êžœ', + 'ꞟ' => 'êžž', + 'êž¡' => 'êž ', + 'ꞣ' => 'Ꞣ', + 'ꞥ' => 'Ꞥ', + 'êž§' => 'Ꞧ', + 'êž©' => 'Ꞩ', + 'ï½' => 'A', + 'b' => 'ï¼¢', + 'c' => 'ï¼£', + 'd' => 'D', + 'ï½…' => 'ï¼¥', + 'f' => 'F', + 'g' => 'ï¼§', + 'h' => 'H', + 'i' => 'I', + 'j' => 'J', + 'k' => 'K', + 'l' => 'L', + 'ï½' => 'ï¼­', + 'n' => 'ï¼®', + 'ï½' => 'O', + 'ï½' => 'ï¼°', + 'q' => 'ï¼±', + 'ï½’' => 'ï¼²', + 's' => 'ï¼³', + 'ï½”' => 'ï¼´', + 'u' => 'ï¼µ', + 'ï½–' => 'ï¼¶', + 'ï½—' => 'ï¼·', + 'x' => 'X', + 'ï½™' => 'ï¼¹', + 'z' => 'Z', + 'ð¨' => 'ð€', + 'ð©' => 'ð', + 'ðª' => 'ð‚', + 'ð«' => 'ðƒ', + 'ð¬' => 'ð„', + 'ð­' => 'ð…', + 'ð®' => 'ð†', + 'ð¯' => 'ð‡', + 'ð°' => 'ðˆ', + 'ð±' => 'ð‰', + 'ð²' => 'ðŠ', + 'ð³' => 'ð‹', + 'ð´' => 'ðŒ', + 'ðµ' => 'ð', + 'ð¶' => 'ðŽ', + 'ð·' => 'ð', + 'ð¸' => 'ð', + 'ð¹' => 'ð‘', + 'ðº' => 'ð’', + 'ð»' => 'ð“', + 'ð¼' => 'ð”', + 'ð½' => 'ð•', + 'ð¾' => 'ð–', + 'ð¿' => 'ð—', + 'ð‘€' => 'ð˜', + 'ð‘' => 'ð™', + 'ð‘‚' => 'ðš', + 'ð‘ƒ' => 'ð›', + 'ð‘„' => 'ðœ', + 'ð‘…' => 'ð', + 'ð‘†' => 'ðž', + 'ð‘‡' => 'ðŸ', + 'ð‘ˆ' => 'ð ', + 'ð‘‰' => 'ð¡', + 'ð‘Š' => 'ð¢', + 'ð‘‹' => 'ð£', + 'ð‘Œ' => 'ð¤', + 'ð‘' => 'ð¥', + 'ð‘Ž' => 'ð¦', + 'ð‘' => 'ð§', + 'ð‘£€' => 'ð‘¢ ', + 'ð‘£' => '𑢡', + '𑣂' => 'ð‘¢¢', + '𑣃' => 'ð‘¢£', + '𑣄' => '𑢤', + 'ð‘£…' => 'ð‘¢¥', + '𑣆' => '𑢦', + '𑣇' => 'ð‘¢§', + '𑣈' => '𑢨', + '𑣉' => '𑢩', + '𑣊' => '𑢪', + '𑣋' => '𑢫', + '𑣌' => '𑢬', + 'ð‘£' => 'ð‘¢­', + '𑣎' => 'ð‘¢®', + 'ð‘£' => '𑢯', + 'ð‘£' => 'ð‘¢°', + '𑣑' => 'ð‘¢±', + 'ð‘£’' => 'ð‘¢²', + '𑣓' => 'ð‘¢³', + 'ð‘£”' => 'ð‘¢´', + '𑣕' => 'ð‘¢µ', + 'ð‘£–' => 'ð‘¢¶', + 'ð‘£—' => 'ð‘¢·', + '𑣘' => '𑢸', + 'ð‘£™' => 'ð‘¢¹', + '𑣚' => '𑢺', + 'ð‘£›' => 'ð‘¢»', + '𑣜' => 'ð‘¢¼', + 'ð‘£' => 'ð‘¢½', + '𑣞' => 'ð‘¢¾', + '𑣟' => '𑢿', +); diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/bootstrap.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/bootstrap.php new file mode 100644 index 0000000..b36a092 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/bootstrap.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Mbstring as p; + +if (!function_exists('mb_convert_encoding')) { + function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); } +} +if (!function_exists('mb_decode_mimeheader')) { + function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); } +} +if (!function_exists('mb_encode_mimeheader')) { + function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); } +} +if (!function_exists('mb_decode_numericentity')) { + function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); } +} +if (!function_exists('mb_encode_numericentity')) { + function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); } +} +if (!function_exists('mb_convert_case')) { + function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); } +} +if (!function_exists('mb_internal_encoding')) { + function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); } +} +if (!function_exists('mb_language')) { + function mb_language($lang = null) { return p\Mbstring::mb_language($lang); } +} +if (!function_exists('mb_list_encodings')) { + function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); } +} +if (!function_exists('mb_encoding_aliases')) { + function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); } +} +if (!function_exists('mb_check_encoding')) { + function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); } +} +if (!function_exists('mb_detect_encoding')) { + function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); } +} +if (!function_exists('mb_detect_order')) { + function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); } +} +if (!function_exists('mb_parse_str')) { + function mb_parse_str($s, &$result = array()) { parse_str($s, $result); } +} +if (!function_exists('mb_strlen')) { + function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); } +} +if (!function_exists('mb_strpos')) { + function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); } +} +if (!function_exists('mb_strtolower')) { + function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); } +} +if (!function_exists('mb_strtoupper')) { + function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); } +} +if (!function_exists('mb_substitute_character')) { + function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); } +} +if (!function_exists('mb_substr')) { + function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); } +} +if (!function_exists('mb_stripos')) { + function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); } +} +if (!function_exists('mb_stristr')) { + function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); } +} +if (!function_exists('mb_strrchr')) { + function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); } +} +if (!function_exists('mb_strrichr')) { + function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); } +} +if (!function_exists('mb_strripos')) { + function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); } +} +if (!function_exists('mb_strrpos')) { + function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); } +} +if (!function_exists('mb_strstr')) { + function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); } +} +if (!function_exists('mb_get_info')) { + function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); } +} +if (!function_exists('mb_http_output')) { + function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); } +} +if (!function_exists('mb_strwidth')) { + function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); } +} +if (!function_exists('mb_substr_count')) { + function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); } +} +if (!function_exists('mb_output_handler')) { + function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); } +} +if (!function_exists('mb_http_input')) { + function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); } +} +if (!function_exists('mb_convert_variables')) { + function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { return p\Mbstring::mb_convert_variables($toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f); } +} +if (!function_exists('mb_ord')) { + function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); } +} +if (!function_exists('mb_chr')) { + function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); } +} +if (!function_exists('mb_scrub')) { + function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); } +} +if (!function_exists('mb_str_split')) { + function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); } +} + +if (extension_loaded('mbstring')) { + return; +} + +if (!defined('MB_CASE_UPPER')) { + define('MB_CASE_UPPER', 0); +} +if (!defined('MB_CASE_LOWER')) { + define('MB_CASE_LOWER', 1); +} +if (!defined('MB_CASE_TITLE')) { + define('MB_CASE_TITLE', 2); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/composer.json b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/composer.json new file mode 100644 index 0000000..d3dcc24 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-mbstring/composer.json @@ -0,0 +1,34 @@ +{ + "name": "symfony/polyfill-mbstring", + "type": "library", + "description": "Symfony polyfill for the Mbstring extension", + "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.17-dev" + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/LICENSE b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/LICENSE new file mode 100644 index 0000000..4cd8bdd --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/Php56.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/Php56.php new file mode 100644 index 0000000..dbbc0e1 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/Php56.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php56; + +use Symfony\Polyfill\Util\Binary; + +/** + * @internal + */ +final class Php56 +{ + const LDAP_ESCAPE_FILTER = 1; + const LDAP_ESCAPE_DN = 2; + + public static function hash_equals($knownString, $userInput) + { + if (!\is_string($knownString)) { + trigger_error('Expected known_string to be a string, '.\gettype($knownString).' given', E_USER_WARNING); + + return false; + } + + if (!\is_string($userInput)) { + trigger_error('Expected user_input to be a string, '.\gettype($userInput).' given', E_USER_WARNING); + + return false; + } + + $knownLen = Binary::strlen($knownString); + $userLen = Binary::strlen($userInput); + + if ($knownLen !== $userLen) { + return false; + } + + $result = 0; + + for ($i = 0; $i < $knownLen; ++$i) { + $result |= \ord($knownString[$i]) ^ \ord($userInput[$i]); + } + + return 0 === $result; + } + + /** + * Stub implementation of the {@link ldap_escape()} function of the ldap + * extension. + * + * Escape strings for safe use in LDAP filters and DNs. + * + * @author Chris Wright + * + * @param string $subject + * @param string $ignore + * @param int $flags + * + * @return string + * + * @see http://stackoverflow.com/a/8561604 + */ + public static function ldap_escape($subject, $ignore = '', $flags = 0) + { + static $charMaps = null; + + if (null === $charMaps) { + $charMaps = array( + self::LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"), + self::LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#', "\r"), + ); + + $charMaps[0] = array(); + + for ($i = 0; $i < 256; ++$i) { + $charMaps[0][\chr($i)] = sprintf('\\%02x', $i); + } + + for ($i = 0, $l = \count($charMaps[self::LDAP_ESCAPE_FILTER]); $i < $l; ++$i) { + $chr = $charMaps[self::LDAP_ESCAPE_FILTER][$i]; + unset($charMaps[self::LDAP_ESCAPE_FILTER][$i]); + $charMaps[self::LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr]; + } + + for ($i = 0, $l = \count($charMaps[self::LDAP_ESCAPE_DN]); $i < $l; ++$i) { + $chr = $charMaps[self::LDAP_ESCAPE_DN][$i]; + unset($charMaps[self::LDAP_ESCAPE_DN][$i]); + $charMaps[self::LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr]; + } + } + + // Create the base char map to escape + $flags = (int) $flags; + $charMap = array(); + + if ($flags & self::LDAP_ESCAPE_FILTER) { + $charMap += $charMaps[self::LDAP_ESCAPE_FILTER]; + } + + if ($flags & self::LDAP_ESCAPE_DN) { + $charMap += $charMaps[self::LDAP_ESCAPE_DN]; + } + + if (!$charMap) { + $charMap = $charMaps[0]; + } + + // Remove any chars to ignore from the list + $ignore = (string) $ignore; + + for ($i = 0, $l = \strlen($ignore); $i < $l; ++$i) { + unset($charMap[$ignore[$i]]); + } + + // Do the main replacement + $result = strtr($subject, $charMap); + + // Encode leading/trailing spaces if self::LDAP_ESCAPE_DN is passed + if ($flags & self::LDAP_ESCAPE_DN) { + if (' ' === $result[0]) { + $result = '\\20'.substr($result, 1); + } + + if (' ' === $result[\strlen($result) - 1]) { + $result = substr($result, 0, -1).'\\20'; + } + } + + return $result; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/README.md b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/README.md new file mode 100644 index 0000000..5ad570b --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/README.md @@ -0,0 +1,15 @@ +Symfony Polyfill / Php56 +======================== + +This component provides functions unavailable in releases prior to PHP 5.6: + +- [`hash_equals`](https://php.net/hash_equals) (part of [hash](https://php.net/hash) extension) +- [`ldap_escape`](https://php.net/ldap_escape) (part of [ldap](https://php.net/ldap) extension) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/bootstrap.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/bootstrap.php new file mode 100644 index 0000000..427dd2e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/bootstrap.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php56 as p; + +if (PHP_VERSION_ID >= 50600) { + return; +} + +if (!function_exists('hash_equals')) { + function hash_equals($knownString, $userInput) { return p\Php56::hash_equals($knownString, $userInput); } +} +if (extension_loaded('ldap') && !defined('LDAP_ESCAPE_FILTER')) { + define('LDAP_ESCAPE_FILTER', 1); +} +if (extension_loaded('ldap') && !defined('LDAP_ESCAPE_DN')) { + define('LDAP_ESCAPE_DN', 2); +} + +if (extension_loaded('ldap') && !function_exists('ldap_escape')) { + function ldap_escape($subject, $ignore = '', $flags = 0) { return p\Php56::ldap_escape($subject, $ignore, $flags); } +} + +if (50509 === PHP_VERSION_ID && 4 === PHP_INT_SIZE) { + // Missing functions in PHP 5.5.9 - affects 32 bit builds of Ubuntu 14.04LTS + // See https://bugs.launchpad.net/ubuntu/+source/php5/+bug/1315888 + if (!function_exists('gzopen') && function_exists('gzopen64')) { + function gzopen($filename, $mode, $use_include_path = 0) { return gzopen64($filename, $mode, $use_include_path); } + } + if (!function_exists('gzseek') && function_exists('gzseek64')) { + function gzseek($zp, $offset, $whence = SEEK_SET) { return gzseek64($zp, $offset, $whence); } + } + if (!function_exists('gztell') && function_exists('gztell64')) { + function gztell($zp) { return gztell64($zp); } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/composer.json b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/composer.json new file mode 100644 index 0000000..e1e969f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-php56/composer.json @@ -0,0 +1,32 @@ +{ + "name": "symfony/polyfill-php56", + "type": "library", + "description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3", + "symfony/polyfill-util": "~1.0" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php56\\": "" }, + "files": [ "bootstrap.php" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.17-dev" + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/Binary.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/Binary.php new file mode 100644 index 0000000..23ff974 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/Binary.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Util; + +if (\extension_loaded('mbstring')) { + class Binary extends BinaryOnFuncOverload + { + } +} else { + class Binary extends BinaryNoFuncOverload + { + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/BinaryNoFuncOverload.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/BinaryNoFuncOverload.php new file mode 100644 index 0000000..800ad75 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/BinaryNoFuncOverload.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Util; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class BinaryNoFuncOverload +{ + public static function strlen($s) + { + return \strlen($s); + } + + public static function strpos($haystack, $needle, $offset = 0) + { + return strpos($haystack, $needle, $offset); + } + + public static function strrpos($haystack, $needle, $offset = 0) + { + return strrpos($haystack, $needle, $offset); + } + + public static function substr($string, $start, $length = PHP_INT_MAX) + { + return substr($string, $start, $length); + } + + public static function stripos($s, $needle, $offset = 0) + { + return stripos($s, $needle, $offset); + } + + public static function stristr($s, $needle, $part = false) + { + return stristr($s, $needle, $part); + } + + public static function strrchr($s, $needle, $part = false) + { + return strrchr($s, $needle, $part); + } + + public static function strripos($s, $needle, $offset = 0) + { + return strripos($s, $needle, $offset); + } + + public static function strstr($s, $needle, $part = false) + { + return strstr($s, $needle, $part); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/BinaryOnFuncOverload.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/BinaryOnFuncOverload.php new file mode 100644 index 0000000..e1b886e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/BinaryOnFuncOverload.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Util; + +/** + * Binary safe version of string functions overloaded when MB_OVERLOAD_STRING is enabled. + * + * @author Nicolas Grekas + * + * @internal + */ +class BinaryOnFuncOverload +{ + public static function strlen($s) + { + return mb_strlen($s, '8bit'); + } + + public static function strpos($haystack, $needle, $offset = 0) + { + return mb_strpos($haystack, $needle, $offset, '8bit'); + } + + public static function strrpos($haystack, $needle, $offset = 0) + { + return mb_strrpos($haystack, $needle, $offset, '8bit'); + } + + public static function substr($string, $start, $length = 2147483647) + { + return mb_substr($string, $start, $length, '8bit'); + } + + public static function stripos($s, $needle, $offset = 0) + { + return mb_stripos($s, $needle, $offset, '8bit'); + } + + public static function stristr($s, $needle, $part = false) + { + return mb_stristr($s, $needle, $part, '8bit'); + } + + public static function strrchr($s, $needle, $part = false) + { + return mb_strrchr($s, $needle, $part, '8bit'); + } + + public static function strripos($s, $needle, $offset = 0) + { + return mb_strripos($s, $needle, $offset, '8bit'); + } + + public static function strstr($s, $needle, $part = false) + { + return mb_strstr($s, $needle, $part, '8bit'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/LICENSE b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/LICENSE new file mode 100644 index 0000000..4cd8bdd --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/README.md b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/README.md new file mode 100644 index 0000000..1c655fc --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/README.md @@ -0,0 +1,13 @@ +Symfony Polyfill / Util +======================= + +This component provides binary-safe string functions, using the +[mbstring](https://php.net/mbstring) extension when available. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListener.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListener.php new file mode 100644 index 0000000..6b17d45 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListener.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Util; + +if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { + class_alias('Symfony\Polyfill\Util\TestListenerForV5', 'Symfony\Polyfill\Util\TestListener'); +// Using an early return instead of a else does not work when using the PHPUnit phar due to some weird PHP behavior (the class +// gets defined without executing the code before it and so the definition is not properly conditional) +} elseif (version_compare(\PHPUnit\Runner\Version::id(), '7.0.0', '<')) { + class_alias('Symfony\Polyfill\Util\TestListenerForV6', 'Symfony\Polyfill\Util\TestListener'); +} else { + class_alias('Symfony\Polyfill\Util\TestListenerForV7', 'Symfony\Polyfill\Util\TestListener'); +} + +if (false) { + class TestListener + { + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerForV5.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerForV5.php new file mode 100644 index 0000000..501053d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerForV5.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Util; + +/** + * @author Nicolas Grekas + */ +class TestListenerForV5 extends \PHPUnit_Framework_TestSuite implements \PHPUnit_Framework_TestListener +{ + private $suite; + private $trait; + + public function __construct(\PHPUnit_Framework_TestSuite $suite = null) + { + if ($suite) { + $this->suite = $suite; + $this->setName($suite->getName().' with polyfills enabled'); + $this->addTest($suite); + } + $this->trait = new TestListenerTrait(); + } + + public function startTestSuite(\PHPUnit_Framework_TestSuite $suite) + { + $this->trait->startTestSuite($suite); + } + + public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time) + { + $this->trait->addError($test, $e, $time); + } + + public function addWarning(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_Warning $e, $time) + { + } + + public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time) + { + $this->trait->addError($test, $e, $time); + } + + public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) + { + } + + public function addRiskyTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) + { + } + + public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) + { + } + + public function endTestSuite(\PHPUnit_Framework_TestSuite $suite) + { + } + + public function startTest(\PHPUnit_Framework_Test $test) + { + } + + public function endTest(\PHPUnit_Framework_Test $test, $time) + { + } + + public static function warning($message) + { + return parent::warning($message); + } + + protected function setUp() + { + TestListenerTrait::$enabledPolyfills = $this->suite->getName(); + } + + protected function tearDown() + { + TestListenerTrait::$enabledPolyfills = false; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerForV6.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerForV6.php new file mode 100644 index 0000000..e9e87cb --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerForV6.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Util; + +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestListener as TestListenerInterface; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; + +/** + * @author Nicolas Grekas + */ +class TestListenerForV6 extends TestSuite implements TestListenerInterface +{ + private $suite; + private $trait; + + public function __construct(TestSuite $suite = null) + { + if ($suite) { + $this->suite = $suite; + $this->setName($suite->getName().' with polyfills enabled'); + $this->addTest($suite); + } + $this->trait = new TestListenerTrait(); + } + + public function startTestSuite(TestSuite $suite) + { + $this->trait->startTestSuite($suite); + } + + public function addError(Test $test, \Exception $e, $time) + { + $this->trait->addError($test, $e, $time); + } + + public function addWarning(Test $test, Warning $e, $time) + { + } + + public function addFailure(Test $test, AssertionFailedError $e, $time) + { + $this->trait->addError($test, $e, $time); + } + + public function addIncompleteTest(Test $test, \Exception $e, $time) + { + } + + public function addRiskyTest(Test $test, \Exception $e, $time) + { + } + + public function addSkippedTest(Test $test, \Exception $e, $time) + { + } + + public function endTestSuite(TestSuite $suite) + { + } + + public function startTest(Test $test) + { + } + + public function endTest(Test $test, $time) + { + } + + public static function warning($message) + { + return parent::warning($message); + } + + protected function setUp() + { + TestListenerTrait::$enabledPolyfills = $this->suite->getName(); + } + + protected function tearDown() + { + TestListenerTrait::$enabledPolyfills = false; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerForV7.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerForV7.php new file mode 100644 index 0000000..a5c3759 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerForV7.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Util; + +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestListener as TestListenerInterface; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; +use PHPUnit\Framework\WarningTestCase; + +/** + * @author Ion Bazan + */ +class TestListenerForV7 extends TestSuite implements TestListenerInterface +{ + private $suite; + private $trait; + + public function __construct(TestSuite $suite = null) + { + if ($suite) { + $this->suite = $suite; + $this->setName($suite->getName().' with polyfills enabled'); + $this->addTest($suite); + } + $this->trait = new TestListenerTrait(); + } + + public function startTestSuite(TestSuite $suite): void + { + $this->trait->startTestSuite($suite); + } + + public function addError(Test $test, \Throwable $t, float $time): void + { + $this->trait->addError($test, $t, $time); + } + + public function addWarning(Test $test, Warning $e, float $time): void + { + } + + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + $this->trait->addError($test, $e, $time); + } + + public function addIncompleteTest(Test $test, \Throwable $t, float $time): void + { + } + + public function addRiskyTest(Test $test, \Throwable $t, float $time): void + { + } + + public function addSkippedTest(Test $test, \Throwable $t, float $time): void + { + } + + public function endTestSuite(TestSuite $suite): void + { + } + + public function startTest(Test $test): void + { + } + + public function endTest(Test $test, float $time): void + { + } + + public static function warning($message): WarningTestCase + { + return new WarningTestCase($message); + } + + protected function setUp(): void + { + TestListenerTrait::$enabledPolyfills = $this->suite->getName(); + } + + protected function tearDown(): void + { + TestListenerTrait::$enabledPolyfills = false; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerTrait.php b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerTrait.php new file mode 100644 index 0000000..777fb48 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/TestListenerTrait.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Util; + +/** + * @author Nicolas Grekas + */ +class TestListenerTrait +{ + public static $enabledPolyfills; + + public function startTestSuite($mainSuite) + { + if (null !== self::$enabledPolyfills) { + return; + } + self::$enabledPolyfills = false; + $SkippedTestError = class_exists('PHPUnit\Framework\SkippedTestError') ? 'PHPUnit\Framework\SkippedTestError' : 'PHPUnit_Framework_SkippedTestError'; + + foreach ($mainSuite->tests() as $suite) { + $testClass = $suite->getName(); + if (!$tests = $suite->tests()) { + continue; + } + $testedClass = new \ReflectionClass($testClass); + if (preg_match('{^ \* @requires PHP (.*)}mi', $testedClass->getDocComment(), $m) && version_compare($m[1], \PHP_VERSION, '>')) { + continue; + } + if (!preg_match('/^(.+)\\\\Tests(\\\\.*)Test$/', $testClass, $m)) { + $mainSuite->addTest(TestListener::warning('Unknown naming convention for '.$testClass)); + continue; + } + if (!class_exists($m[1].$m[2])) { + continue; + } + $testedClass = new \ReflectionClass($m[1].$m[2]); + $bootstrap = new \SplFileObject(\dirname($testedClass->getFileName()).'/bootstrap.php'); + $warnings = array(); + $defLine = null; + + foreach (new \RegexIterator($bootstrap, '/define\(\'/') as $defLine) { + preg_match('/define\(\'(?P.+)\'/', $defLine, $matches); + if (\defined($matches['name'])) { + continue; + } + + try { + eval($defLine); + } catch (\PHPUnit_Framework_Exception $ex){ + $warnings[] = TestListener::warning($ex->getMessage()); + } catch (\PHPUnit\Framework\Exception $ex) { + $warnings[] = TestListener::warning($ex->getMessage()); + } + } + + $bootstrap->rewind(); + + foreach (new \RegexIterator($bootstrap, '/return p\\\\'.$testedClass->getShortName().'::/') as $defLine) { + if (!preg_match('/^\s*function (?P[^\(]++)(?P\(.*\)(?: ?: [^ ]++)?) \{ (?return p\\\\'.$testedClass->getShortName().'::[^\(]++)(?P\([^\)]*+\)); \}$/', $defLine, $f)) { + $warnings[] = TestListener::warning('Invalid line in bootstrap.php: '.trim($defLine)); + continue; + } + $testNamespace = substr($testClass, 0, strrpos($testClass, '\\')); + if (\function_exists($testNamespace.'\\'.$f['name'])) { + continue; + } + + try { + $r = new \ReflectionFunction($f['name']); + if ($r->isUserDefined()) { + throw new \ReflectionException(); + } + if ('idn_to_ascii' === $f['name'] || 'idn_to_utf8' === $f['name']) { + $defLine = sprintf('return INTL_IDNA_VARIANT_2003 === $variant ? \\%s($domain, $options, $variant) : \\%1$s%s', $f['name'], $f['args']); + } elseif (false !== strpos($f['signature'], '&') && 'idn_to_ascii' !== $f['name'] && 'idn_to_utf8' !== $f['name']) { + $defLine = sprintf('return \\%s%s', $f['name'], $f['args']); + } else { + $defLine = sprintf("return \\call_user_func_array('%s', \\func_get_args())", $f['name']); + } + } catch (\ReflectionException $e) { + $defLine = sprintf("throw new \\{$SkippedTestError}('Internal function not found: %s')", $f['name']); + } + + eval(<<getNamespaceName()} as p; + +function {$f['name']}{$f['signature']} +{ + if ('{$testClass}' === TestListenerTrait::\$enabledPolyfills) { + {$f['return']}{$f['args']}; + } + + {$defLine}; +} +EOPHP + ); + } + if (!$warnings && null === $defLine) { + $warnings[] = new $SkippedTestError('No Polyfills found in bootstrap.php for '.$testClass); + } else { + $mainSuite->addTest(new TestListener($suite)); + } + } + foreach ($warnings as $w) { + $mainSuite->addTest($w); + } + } + + public function addError($test, \Exception $e, $time) + { + if (false !== self::$enabledPolyfills) { + $r = new \ReflectionProperty('Exception', 'message'); + $r->setAccessible(true); + $r->setValue($e, 'Polyfills enabled, '.$r->getValue($e)); + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/composer.json b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/composer.json new file mode 100644 index 0000000..1ab79ac --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/polyfill-util/composer.json @@ -0,0 +1,30 @@ +{ + "name": "symfony/polyfill-util", + "type": "library", + "description": "Symfony utilities for portability of PHP codes", + "keywords": ["polyfill", "shim", "compat", "compatibility"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Util\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.17-dev" + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/CHANGELOG.md b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/CHANGELOG.md new file mode 100644 index 0000000..e984777 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/CHANGELOG.md @@ -0,0 +1,5 @@ +CHANGELOG +========= + +The changelog is maintained for all Symfony contracts at the following URL: +https://github.com/symfony/contracts/blob/master/CHANGELOG.md diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/LICENSE b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/LICENSE new file mode 100644 index 0000000..69d925b --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2020 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/LocaleAwareInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/LocaleAwareInterface.php new file mode 100644 index 0000000..922ec1d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/LocaleAwareInterface.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Translation; + +interface LocaleAwareInterface +{ + /** + * Sets the current locale. + * + * @param string $locale The locale + * + * @throws \InvalidArgumentException If the locale contains invalid characters + */ + public function setLocale(string $locale); + + /** + * Returns the current locale. + * + * @return string The locale + */ + public function getLocale(); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/README.md b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/README.md new file mode 100644 index 0000000..6c693ce --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/README.md @@ -0,0 +1,9 @@ +Symfony Translation Contracts +============================= + +A set of abstractions extracted out of the Symfony components. + +Can be used to build on semantics that the Symfony components proved useful - and +that already have battle tested implementations. + +See https://github.com/symfony/contracts/blob/master/README.md for more information. diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/Test/TranslatorTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/Test/TranslatorTest.php new file mode 100644 index 0000000..5bfb0f8 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/Test/TranslatorTest.php @@ -0,0 +1,353 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Translation\Test; + +use PHPUnit\Framework\TestCase; +use Symfony\Contracts\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorTrait; + +/** + * Test should cover all languages mentioned on http://translate.sourceforge.net/wiki/l10n/pluralforms + * and Plural forms mentioned on http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms. + * + * See also https://developer.mozilla.org/en/Localization_and_Plurals which mentions 15 rules having a maximum of 6 forms. + * The mozilla code is also interesting to check for. + * + * As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199 + * + * The goal to cover all languages is to far fetched so this test case is smaller. + * + * @author Clemens Tolboom clemens@build2be.nl + */ +class TranslatorTest extends TestCase +{ + public function getTranslator() + { + return new class() implements TranslatorInterface { + use TranslatorTrait; + }; + } + + /** + * @dataProvider getTransTests + */ + public function testTrans($expected, $id, $parameters) + { + $translator = $this->getTranslator(); + + $this->assertEquals($expected, $translator->trans($id, $parameters)); + } + + /** + * @dataProvider getTransChoiceTests + */ + public function testTransChoiceWithExplicitLocale($expected, $id, $number) + { + $translator = $this->getTranslator(); + $translator->setLocale('en'); + + $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number])); + } + + /** + * @dataProvider getTransChoiceTests + */ + public function testTransChoiceWithDefaultLocale($expected, $id, $number) + { + \Locale::setDefault('en'); + + $translator = $this->getTranslator(); + + $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number])); + } + + public function testGetSetLocale() + { + $translator = $this->getTranslator(); + $translator->setLocale('en'); + + $this->assertEquals('en', $translator->getLocale()); + } + + /** + * @requires extension intl + */ + public function testGetLocaleReturnsDefaultLocaleIfNotSet() + { + $translator = $this->getTranslator(); + + \Locale::setDefault('pt_BR'); + $this->assertEquals('pt_BR', $translator->getLocale()); + + \Locale::setDefault('en'); + $this->assertEquals('en', $translator->getLocale()); + } + + public function getTransTests() + { + return [ + ['Symfony is great!', 'Symfony is great!', []], + ['Symfony is awesome!', 'Symfony is %what%!', ['%what%' => 'awesome']], + ]; + } + + public function getTransChoiceTests() + { + return [ + ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], + ['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1], + ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10], + ['There are 0 apples', 'There is 1 apple|There are %count% apples', 0], + ['There is 1 apple', 'There is 1 apple|There are %count% apples', 1], + ['There are 10 apples', 'There is 1 apple|There are %count% apples', 10], + // custom validation messages may be coded with a fixed value + ['There are 2 apples', 'There are 2 apples', 2], + ]; + } + + /** + * @dataProvider getInternal + */ + public function testInterval($expected, $number, $interval) + { + $translator = $this->getTranslator(); + + $this->assertEquals($expected, $translator->trans($interval.' foo|[1,Inf[ bar', ['%count%' => $number])); + } + + public function getInternal() + { + return [ + ['foo', 3, '{1,2, 3 ,4}'], + ['bar', 10, '{1,2, 3 ,4}'], + ['bar', 3, '[1,2]'], + ['foo', 1, '[1,2]'], + ['foo', 2, '[1,2]'], + ['bar', 1, ']1,2['], + ['bar', 2, ']1,2['], + ['foo', log(0), '[-Inf,2['], + ['foo', -log(0), '[-2,+Inf]'], + ]; + } + + /** + * @dataProvider getChooseTests + */ + public function testChoose($expected, $id, $number) + { + $translator = $this->getTranslator(); + + $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number])); + } + + public function testReturnMessageIfExactlyOneStandardRuleIsGiven() + { + $translator = $this->getTranslator(); + + $this->assertEquals('There are two apples', $translator->trans('There are two apples', ['%count%' => 2])); + } + + /** + * @dataProvider getNonMatchingMessages + */ + public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number) + { + $this->expectException('InvalidArgumentException'); + $translator = $this->getTranslator(); + + $translator->trans($id, ['%count%' => $number]); + } + + public function getNonMatchingMessages() + { + return [ + ['{0} There are no apples|{1} There is one apple', 2], + ['{1} There is one apple|]1,Inf] There are %count% apples', 0], + ['{1} There is one apple|]2,Inf] There are %count% apples', 2], + ['{0} There are no apples|There is one apple', 2], + ]; + } + + public function getChooseTests() + { + return [ + ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], + ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], + ['There are no apples', '{0}There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], + + ['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1], + + ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10], + ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10], + ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10], + + ['There are 0 apples', 'There is one apple|There are %count% apples', 0], + ['There is one apple', 'There is one apple|There are %count% apples', 1], + ['There are 10 apples', 'There is one apple|There are %count% apples', 10], + + ['There are 0 apples', 'one: There is one apple|more: There are %count% apples', 0], + ['There is one apple', 'one: There is one apple|more: There are %count% apples', 1], + ['There are 10 apples', 'one: There is one apple|more: There are %count% apples', 10], + + ['There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0], + ['There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1], + ['There are 10 apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10], + + ['', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0], + ['', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1], + + // Indexed only tests which are Gettext PoFile* compatible strings. + ['There are 0 apples', 'There is one apple|There are %count% apples', 0], + ['There is one apple', 'There is one apple|There are %count% apples', 1], + ['There are 2 apples', 'There is one apple|There are %count% apples', 2], + + // Tests for float numbers + ['There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7], + ['There is one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1], + ['There is more than one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1.7], + ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0], + ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0.0], + ['There are no apples', '{0.0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0], + + // Test texts with new-lines + // with double-quotes and \n in id & double-quotes and actual newlines in text + ["This is a text with a\n new-line in it. Selector = 0.", '{0}This is a text with a + new-line in it. Selector = 0.|{1}This is a text with a + new-line in it. Selector = 1.|[1,Inf]This is a text with a + new-line in it. Selector > 1.', 0], + // with double-quotes and \n in id and single-quotes and actual newlines in text + ["This is a text with a\n new-line in it. Selector = 1.", '{0}This is a text with a + new-line in it. Selector = 0.|{1}This is a text with a + new-line in it. Selector = 1.|[1,Inf]This is a text with a + new-line in it. Selector > 1.', 1], + ["This is a text with a\n new-line in it. Selector > 1.", '{0}This is a text with a + new-line in it. Selector = 0.|{1}This is a text with a + new-line in it. Selector = 1.|[1,Inf]This is a text with a + new-line in it. Selector > 1.', 5], + // with double-quotes and id split accros lines + ['This is a text with a + new-line in it. Selector = 1.', '{0}This is a text with a + new-line in it. Selector = 0.|{1}This is a text with a + new-line in it. Selector = 1.|[1,Inf]This is a text with a + new-line in it. Selector > 1.', 1], + // with single-quotes and id split accros lines + ['This is a text with a + new-line in it. Selector > 1.', '{0}This is a text with a + new-line in it. Selector = 0.|{1}This is a text with a + new-line in it. Selector = 1.|[1,Inf]This is a text with a + new-line in it. Selector > 1.', 5], + // with single-quotes and \n in text + ['This is a text with a\nnew-line in it. Selector = 0.', '{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.', 0], + // with double-quotes and id split accros lines + ["This is a text with a\nnew-line in it. Selector = 1.", "{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.", 1], + // esacape pipe + ['This is a text with | in it. Selector = 0.', '{0}This is a text with || in it. Selector = 0.|{1}This is a text with || in it. Selector = 1.', 0], + // Empty plural set (2 plural forms) from a .PO file + ['', '|', 1], + // Empty plural set (3 plural forms) from a .PO file + ['', '||', 1], + ]; + } + + /** + * @dataProvider failingLangcodes + */ + public function testFailedLangcodes($nplural, $langCodes) + { + $matrix = $this->generateTestData($langCodes); + $this->validateMatrix($nplural, $matrix, false); + } + + /** + * @dataProvider successLangcodes + */ + public function testLangcodes($nplural, $langCodes) + { + $matrix = $this->generateTestData($langCodes); + $this->validateMatrix($nplural, $matrix); + } + + /** + * This array should contain all currently known langcodes. + * + * As it is impossible to have this ever complete we should try as hard as possible to have it almost complete. + * + * @return array + */ + public function successLangcodes() + { + return [ + ['1', ['ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky']], + ['2', ['nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM']], + ['3', ['be', 'bs', 'cs', 'hr']], + ['4', ['cy', 'mt', 'sl']], + ['6', ['ar']], + ]; + } + + /** + * This array should be at least empty within the near future. + * + * This both depends on a complete list trying to add above as understanding + * the plural rules of the current failing languages. + * + * @return array with nplural together with langcodes + */ + public function failingLangcodes() + { + return [ + ['1', ['fa']], + ['2', ['jbo']], + ['3', ['cbs']], + ['4', ['gd', 'kw']], + ['5', ['ga']], + ]; + } + + /** + * We validate only on the plural coverage. Thus the real rules is not tested. + * + * @param string $nplural Plural expected + * @param array $matrix Containing langcodes and their plural index values + * @param bool $expectSuccess + */ + protected function validateMatrix($nplural, $matrix, $expectSuccess = true) + { + foreach ($matrix as $langCode => $data) { + $indexes = array_flip($data); + if ($expectSuccess) { + $this->assertEquals($nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms."); + } else { + $this->assertNotEquals((int) $nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms."); + } + } + } + + protected function generateTestData($langCodes) + { + $translator = new class() { + use TranslatorTrait { + getPluralizationRule as public; + } + }; + + $matrix = []; + foreach ($langCodes as $langCode) { + for ($count = 0; $count < 200; ++$count) { + $plural = $translator->getPluralizationRule($count, $langCode); + $matrix[$langCode][$count] = $plural; + } + } + + return $matrix; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/TranslatorInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/TranslatorInterface.php new file mode 100644 index 0000000..b62df5e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/TranslatorInterface.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Translation; + +/** + * @author Fabien Potencier + */ +interface TranslatorInterface +{ + /** + * Translates the given message. + * + * When a number is provided as a parameter named "%count%", the message is parsed for plural + * forms and a translation is chosen according to this number using the following rules: + * + * Given a message with different plural translations separated by a + * pipe (|), this method returns the correct portion of the message based + * on the given number, locale and the pluralization rules in the message + * itself. + * + * The message supports two different types of pluralization rules: + * + * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples + * indexed: There is one apple|There are %count% apples + * + * The indexed solution can also contain labels (e.g. one: There is one apple). + * This is purely for making the translations more clear - it does not + * affect the functionality. + * + * The two methods can also be mixed: + * {0} There are no apples|one: There is one apple|more: There are %count% apples + * + * An interval can represent a finite set of numbers: + * {1,2,3,4} + * + * An interval can represent numbers between two numbers: + * [1, +Inf] + * ]-1,2[ + * + * The left delimiter can be [ (inclusive) or ] (exclusive). + * The right delimiter can be [ (exclusive) or ] (inclusive). + * Beside numbers, you can use -Inf and +Inf for the infinite. + * + * @see https://en.wikipedia.org/wiki/ISO_31-11 + * + * @param string $id The message id (may also be an object that can be cast to string) + * @param array $parameters An array of parameters for the message + * @param string|null $domain The domain for the message or null to use the default + * @param string|null $locale The locale or null to use the default + * + * @return string The translated string + * + * @throws \InvalidArgumentException If the locale contains invalid characters + */ + public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/TranslatorTrait.php b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/TranslatorTrait.php new file mode 100644 index 0000000..f81637a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/TranslatorTrait.php @@ -0,0 +1,257 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Translation; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; + +/** + * A trait to help implement TranslatorInterface and LocaleAwareInterface. + * + * @author Fabien Potencier + */ +trait TranslatorTrait +{ + private $locale; + + /** + * {@inheritdoc} + */ + public function setLocale(string $locale) + { + $this->locale = $locale; + } + + /** + * {@inheritdoc} + */ + public function getLocale() + { + return $this->locale ?: \Locale::getDefault(); + } + + /** + * {@inheritdoc} + */ + public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null): string + { + if (null === $id || '' === $id) { + return ''; + } + + if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) { + return strtr($id, $parameters); + } + + $number = (float) $parameters['%count%']; + $locale = $locale ?: $this->getLocale(); + + $parts = []; + if (preg_match('/^\|++$/', $id)) { + $parts = explode('|', $id); + } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) { + $parts = $matches[0]; + } + + $intervalRegexp = <<<'EOF' +/^(?P + ({\s* + (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*) + \s*}) + + | + + (?P[\[\]]) + \s* + (?P-Inf|\-?\d+(\.\d+)?) + \s*,\s* + (?P\+?Inf|\-?\d+(\.\d+)?) + \s* + (?P[\[\]]) +)\s*(?P.*?)$/xs +EOF; + + $standardRules = []; + foreach ($parts as $part) { + $part = trim(str_replace('||', '|', $part)); + + // try to match an explicit rule, then fallback to the standard ones + if (preg_match($intervalRegexp, $part, $matches)) { + if ($matches[2]) { + foreach (explode(',', $matches[3]) as $n) { + if ($number == $n) { + return strtr($matches['message'], $parameters); + } + } + } else { + $leftNumber = '-Inf' === $matches['left'] ? -INF : (float) $matches['left']; + $rightNumber = is_numeric($matches['right']) ? (float) $matches['right'] : INF; + + if (('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber) + && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber) + ) { + return strtr($matches['message'], $parameters); + } + } + } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) { + $standardRules[] = $matches[1]; + } else { + $standardRules[] = $part; + } + } + + $position = $this->getPluralizationRule($number, $locale); + + if (!isset($standardRules[$position])) { + // when there's exactly one rule given, and that rule is a standard + // rule, use this rule + if (1 === \count($parts) && isset($standardRules[0])) { + return strtr($standardRules[0], $parameters); + } + + $message = sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $id, $locale, $number); + + if (class_exists(InvalidArgumentException::class)) { + throw new InvalidArgumentException($message); + } + + throw new \InvalidArgumentException($message); + } + + return strtr($standardRules[$position], $parameters); + } + + /** + * Returns the plural position to use for the given locale and number. + * + * The plural rules are derived from code of the Zend Framework (2010-09-25), + * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd). + * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + */ + private function getPluralizationRule(int $number, string $locale): int + { + switch ('pt_BR' !== $locale && \strlen($locale) > 3 ? substr($locale, 0, strrpos($locale, '_')) : $locale) { + case 'af': + case 'bn': + case 'bg': + case 'ca': + case 'da': + case 'de': + case 'el': + case 'en': + case 'eo': + case 'es': + case 'et': + case 'eu': + case 'fa': + case 'fi': + case 'fo': + case 'fur': + case 'fy': + case 'gl': + case 'gu': + case 'ha': + case 'he': + case 'hu': + case 'is': + case 'it': + case 'ku': + case 'lb': + case 'ml': + case 'mn': + case 'mr': + case 'nah': + case 'nb': + case 'ne': + case 'nl': + case 'nn': + case 'no': + case 'oc': + case 'om': + case 'or': + case 'pa': + case 'pap': + case 'ps': + case 'pt': + case 'so': + case 'sq': + case 'sv': + case 'sw': + case 'ta': + case 'te': + case 'tk': + case 'ur': + case 'zu': + return (1 == $number) ? 0 : 1; + + case 'am': + case 'bh': + case 'fil': + case 'fr': + case 'gun': + case 'hi': + case 'hy': + case 'ln': + case 'mg': + case 'nso': + case 'pt_BR': + case 'ti': + case 'wa': + return ((0 == $number) || (1 == $number)) ? 0 : 1; + + case 'be': + case 'bs': + case 'hr': + case 'ru': + case 'sh': + case 'sr': + case 'uk': + return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); + + case 'cs': + case 'sk': + return (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); + + case 'ga': + return (1 == $number) ? 0 : ((2 == $number) ? 1 : 2); + + case 'lt': + return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); + + case 'sl': + return (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3)); + + case 'mk': + return (1 == $number % 10) ? 0 : 1; + + case 'mt': + return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); + + case 'lv': + return (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2); + + case 'pl': + return (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); + + case 'cy': + return (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3)); + + case 'ro': + return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); + + case 'ar': + return (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5)))); + + default: + return 0; + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/composer.json b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/composer.json new file mode 100644 index 0000000..cacc4b3 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation-contracts/composer.json @@ -0,0 +1,33 @@ +{ + "name": "symfony/translation-contracts", + "type": "library", + "description": "Generic abstractions related to translation", + "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\Translation\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/CHANGELOG.md b/plugins/vdomah/jwtauth/vendor/symfony/translation/CHANGELOG.md new file mode 100644 index 0000000..9784532 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/CHANGELOG.md @@ -0,0 +1,133 @@ +CHANGELOG +========= + +4.4.0 +----- + + * deprecated support for using `null` as the locale in `Translator` + * deprecated accepting STDIN implicitly when using the `lint:xliff` command, use `lint:xliff -` (append a dash) instead to make it explicit. + * Marked the `TranslationDataCollector` class as `@final`. + +4.3.0 +----- + + * Improved Xliff 1.2 loader to load the original file's metadata + * Added `TranslatorPathsPass` + +4.2.0 +----- + + * Started using ICU parent locales as fallback locales. + * allow using the ICU message format using domains with the "+intl-icu" suffix + * deprecated `Translator::transChoice()` in favor of using `Translator::trans()` with a `%count%` parameter + * deprecated `TranslatorInterface` in favor of `Symfony\Contracts\Translation\TranslatorInterface` + * deprecated `MessageSelector`, `Interval` and `PluralizationRules`; use `IdentityTranslator` instead + * Added `IntlFormatter` and `IntlFormatterInterface` + * added support for multiple files and directories in `XliffLintCommand` + * Marked `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` as internal + +4.1.0 +----- + + * The `FileDumper::setBackup()` method is deprecated. + * The `TranslationWriter::disableBackup()` method is deprecated. + * The `XliffFileDumper` will write "name" on the "unit" node when dumping XLIFF 2.0. + +4.0.0 +----- + + * removed the backup feature of the `FileDumper` class + * removed `TranslationWriter::writeTranslations()` method + * removed support for passing `MessageSelector` instances to the constructor of the `Translator` class + +3.4.0 +----- + + * Added `TranslationDumperPass` + * Added `TranslationExtractorPass` + * Added `TranslatorPass` + * Added `TranslationReader` and `TranslationReaderInterface` + * Added `` section to the Xliff 2.0 dumper. + * Improved Xliff 2.0 loader to load `` section. + * Added `TranslationWriterInterface` + * Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write` + * added support for adding custom message formatter and decoupling the default one. + * Added `PhpExtractor` + * Added `PhpStringTokenParser` + +3.2.0 +----- + + * Added support for escaping `|` in plural translations with double pipe. + +3.1.0 +----- + + * Deprecated the backup feature of the file dumper classes. + +3.0.0 +----- + + * removed `FileDumper::format()` method. + * Changed the visibility of the locale property in `Translator` from protected to private. + +2.8.0 +----- + + * deprecated FileDumper::format(), overwrite FileDumper::formatCatalogue() instead. + * deprecated Translator::getMessages(), rely on TranslatorBagInterface::getCatalogue() instead. + * added `FileDumper::formatCatalogue` which allows format the catalogue without dumping it into file. + * added option `json_encoding` to JsonFileDumper + * added options `as_tree`, `inline` to YamlFileDumper + * added support for XLIFF 2.0. + * added support for XLIFF target and tool attributes. + * added message parameters to DataCollectorTranslator. + * [DEPRECATION] The `DiffOperation` class has been deprecated and + will be removed in Symfony 3.0, since its operation has nothing to do with 'diff', + so the class name is misleading. The `TargetOperation` class should be used for + this use-case instead. + +2.7.0 +----- + + * added DataCollectorTranslator for collecting the translated messages. + +2.6.0 +----- + + * added possibility to cache catalogues + * added TranslatorBagInterface + * added LoggingTranslator + * added Translator::getMessages() for retrieving the message catalogue as an array + +2.5.0 +----- + + * added relative file path template to the file dumpers + * added optional backup to the file dumpers + * changed IcuResFileDumper to extend FileDumper + +2.3.0 +----- + + * added classes to make operations on catalogues (like making a diff or a merge on 2 catalogues) + * added Translator::getFallbackLocales() + * deprecated Translator::setFallbackLocale() in favor of the new Translator::setFallbackLocales() method + +2.2.0 +----- + + * QtTranslationsLoader class renamed to QtFileLoader. QtTranslationsLoader is deprecated and will be removed in 2.3. + * [BC BREAK] uniformized the exception thrown by the load() method when an error occurs. The load() method now + throws Symfony\Component\Translation\Exception\NotFoundResourceException when a resource cannot be found + and Symfony\Component\Translation\Exception\InvalidResourceException when a resource is invalid. + * changed the exception class thrown by some load() methods from \RuntimeException to \InvalidArgumentException + (IcuDatFileLoader, IcuResFileLoader and QtFileLoader) + +2.1.0 +----- + + * added support for more than one fallback locale + * added support for extracting translation messages from templates (Twig and PHP) + * added dumpers for translation catalogs + * added support for QT, gettext, and ResourceBundles diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/AbstractOperation.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/AbstractOperation.php new file mode 100644 index 0000000..4953563 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/AbstractOperation.php @@ -0,0 +1,157 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Catalogue; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\LogicException; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\MessageCatalogueInterface; + +/** + * Base catalogues binary operation class. + * + * A catalogue binary operation performs operation on + * source (the left argument) and target (the right argument) catalogues. + * + * @author Jean-François Simon + */ +abstract class AbstractOperation implements OperationInterface +{ + protected $source; + protected $target; + protected $result; + + /** + * @var array|null The domains affected by this operation + */ + private $domains; + + /** + * This array stores 'all', 'new' and 'obsolete' messages for all valid domains. + * + * The data structure of this array is as follows: + * + * [ + * 'domain 1' => [ + * 'all' => [...], + * 'new' => [...], + * 'obsolete' => [...] + * ], + * 'domain 2' => [ + * 'all' => [...], + * 'new' => [...], + * 'obsolete' => [...] + * ], + * ... + * ] + * + * @var array The array that stores 'all', 'new' and 'obsolete' messages + */ + protected $messages; + + /** + * @throws LogicException + */ + public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target) + { + if ($source->getLocale() !== $target->getLocale()) { + throw new LogicException('Operated catalogues must belong to the same locale.'); + } + + $this->source = $source; + $this->target = $target; + $this->result = new MessageCatalogue($source->getLocale()); + $this->messages = []; + } + + /** + * {@inheritdoc} + */ + public function getDomains() + { + if (null === $this->domains) { + $this->domains = array_values(array_unique(array_merge($this->source->getDomains(), $this->target->getDomains()))); + } + + return $this->domains; + } + + /** + * {@inheritdoc} + */ + public function getMessages($domain) + { + if (!\in_array($domain, $this->getDomains())) { + throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain)); + } + + if (!isset($this->messages[$domain]['all'])) { + $this->processDomain($domain); + } + + return $this->messages[$domain]['all']; + } + + /** + * {@inheritdoc} + */ + public function getNewMessages($domain) + { + if (!\in_array($domain, $this->getDomains())) { + throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain)); + } + + if (!isset($this->messages[$domain]['new'])) { + $this->processDomain($domain); + } + + return $this->messages[$domain]['new']; + } + + /** + * {@inheritdoc} + */ + public function getObsoleteMessages($domain) + { + if (!\in_array($domain, $this->getDomains())) { + throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain)); + } + + if (!isset($this->messages[$domain]['obsolete'])) { + $this->processDomain($domain); + } + + return $this->messages[$domain]['obsolete']; + } + + /** + * {@inheritdoc} + */ + public function getResult() + { + foreach ($this->getDomains() as $domain) { + if (!isset($this->messages[$domain])) { + $this->processDomain($domain); + } + } + + return $this->result; + } + + /** + * Performs operation on source and target catalogues for the given domain and + * stores the results. + * + * @param string $domain The domain which the operation will be performed for + */ + abstract protected function processDomain($domain); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/MergeOperation.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/MergeOperation.php new file mode 100644 index 0000000..d2f4abd --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/MergeOperation.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Catalogue; + +use Symfony\Component\Translation\MessageCatalogueInterface; + +/** + * Merge operation between two catalogues as follows: + * all = source ∪ target = {x: x ∈ source ∨ x ∈ target} + * new = all ∖ source = {x: x ∈ target ∧ x ∉ source} + * obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ source ∧ x ∉ target} = ∅ + * Basically, the result contains messages from both catalogues. + * + * @author Jean-François Simon + */ +class MergeOperation extends AbstractOperation +{ + /** + * {@inheritdoc} + */ + protected function processDomain($domain) + { + $this->messages[$domain] = [ + 'all' => [], + 'new' => [], + 'obsolete' => [], + ]; + $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX; + + foreach ($this->source->all($domain) as $id => $message) { + $this->messages[$domain]['all'][$id] = $message; + $this->result->add([$id => $message], $this->source->defines($id, $intlDomain) ? $intlDomain : $domain); + if (null !== $keyMetadata = $this->source->getMetadata($id, $domain)) { + $this->result->setMetadata($id, $keyMetadata, $domain); + } + } + + foreach ($this->target->all($domain) as $id => $message) { + if (!$this->source->has($id, $domain)) { + $this->messages[$domain]['all'][$id] = $message; + $this->messages[$domain]['new'][$id] = $message; + $this->result->add([$id => $message], $this->target->defines($id, $intlDomain) ? $intlDomain : $domain); + if (null !== $keyMetadata = $this->target->getMetadata($id, $domain)) { + $this->result->setMetadata($id, $keyMetadata, $domain); + } + } + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/OperationInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/OperationInterface.php new file mode 100644 index 0000000..87d888e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/OperationInterface.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Catalogue; + +use Symfony\Component\Translation\MessageCatalogueInterface; + +/** + * Represents an operation on catalogue(s). + * + * An instance of this interface performs an operation on one or more catalogues and + * stores intermediate and final results of the operation. + * + * The first catalogue in its argument(s) is called the 'source catalogue' or 'source' and + * the following results are stored: + * + * Messages: also called 'all', are valid messages for the given domain after the operation is performed. + * + * New Messages: also called 'new' (new = all ∖ source = {x: x ∈ all ∧ x ∉ source}). + * + * Obsolete Messages: also called 'obsolete' (obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ all}). + * + * Result: also called 'result', is the resulting catalogue for the given domain that holds the same messages as 'all'. + * + * @author Jean-François Simon + */ +interface OperationInterface +{ + /** + * Returns domains affected by operation. + * + * @return array + */ + public function getDomains(); + + /** + * Returns all valid messages ('all') after operation. + * + * @param string $domain + * + * @return array + */ + public function getMessages($domain); + + /** + * Returns new messages ('new') after operation. + * + * @param string $domain + * + * @return array + */ + public function getNewMessages($domain); + + /** + * Returns obsolete messages ('obsolete') after operation. + * + * @param string $domain + * + * @return array + */ + public function getObsoleteMessages($domain); + + /** + * Returns resulting catalogue ('result'). + * + * @return MessageCatalogueInterface + */ + public function getResult(); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/TargetOperation.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/TargetOperation.php new file mode 100644 index 0000000..22aa9a3 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Catalogue/TargetOperation.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Catalogue; + +use Symfony\Component\Translation\MessageCatalogueInterface; + +/** + * Target operation between two catalogues: + * intersection = source ∩ target = {x: x ∈ source ∧ x ∈ target} + * all = intersection ∪ (target ∖ intersection) = target + * new = all ∖ source = {x: x ∈ target ∧ x ∉ source} + * obsolete = source ∖ all = source ∖ target = {x: x ∈ source ∧ x ∉ target} + * Basically, the result contains messages from the target catalogue. + * + * @author Michael Lee + */ +class TargetOperation extends AbstractOperation +{ + /** + * {@inheritdoc} + */ + protected function processDomain($domain) + { + $this->messages[$domain] = [ + 'all' => [], + 'new' => [], + 'obsolete' => [], + ]; + $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX; + + // For 'all' messages, the code can't be simplified as ``$this->messages[$domain]['all'] = $target->all($domain);``, + // because doing so will drop messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback} + // + // For 'new' messages, the code can't be simplified as ``array_diff_assoc($this->target->all($domain), $this->source->all($domain));`` + // because doing so will not exclude messages like {x: x ∈ target ∧ x ∉ source.all ∧ x ∈ source.fallback} + // + // For 'obsolete' messages, the code can't be simplified as ``array_diff_assoc($this->source->all($domain), $this->target->all($domain))`` + // because doing so will not exclude messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback} + + foreach ($this->source->all($domain) as $id => $message) { + if ($this->target->has($id, $domain)) { + $this->messages[$domain]['all'][$id] = $message; + $this->result->add([$id => $message], $this->target->defines($id, $intlDomain) ? $intlDomain : $domain); + if (null !== $keyMetadata = $this->source->getMetadata($id, $domain)) { + $this->result->setMetadata($id, $keyMetadata, $domain); + } + } else { + $this->messages[$domain]['obsolete'][$id] = $message; + } + } + + foreach ($this->target->all($domain) as $id => $message) { + if (!$this->source->has($id, $domain)) { + $this->messages[$domain]['all'][$id] = $message; + $this->messages[$domain]['new'][$id] = $message; + $this->result->add([$id => $message], $this->target->defines($id, $intlDomain) ? $intlDomain : $domain); + if (null !== $keyMetadata = $this->target->getMetadata($id, $domain)) { + $this->result->setMetadata($id, $keyMetadata, $domain); + } + } + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Command/XliffLintCommand.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Command/XliffLintCommand.php new file mode 100644 index 0000000..3f8fe73 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Command/XliffLintCommand.php @@ -0,0 +1,273 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Util\XliffUtils; + +/** + * Validates XLIFF files syntax and outputs encountered errors. + * + * @author Grégoire Pineau + * @author Robin Chalas + * @author Javier Eguiluz + */ +class XliffLintCommand extends Command +{ + protected static $defaultName = 'lint:xliff'; + + private $format; + private $displayCorrectFiles; + private $directoryIteratorProvider; + private $isReadableProvider; + private $requireStrictFileNames; + + public function __construct(string $name = null, callable $directoryIteratorProvider = null, callable $isReadableProvider = null, bool $requireStrictFileNames = true) + { + parent::__construct($name); + + $this->directoryIteratorProvider = $directoryIteratorProvider; + $this->isReadableProvider = $isReadableProvider; + $this->requireStrictFileNames = $requireStrictFileNames; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDescription('Lints a XLIFF file and outputs encountered errors') + ->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN') + ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') + ->setHelp(<<%command.name% command lints a XLIFF file and outputs to STDOUT +the first encountered syntax error. + +You can validates XLIFF contents passed from STDIN: + + cat filename | php %command.full_name% - + +You can also validate the syntax of a file: + + php %command.full_name% filename + +Or of a whole directory: + + php %command.full_name% dirname + php %command.full_name% dirname --format=json + +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $io = new SymfonyStyle($input, $output); + $filenames = (array) $input->getArgument('filename'); + $this->format = $input->getOption('format'); + $this->displayCorrectFiles = $output->isVerbose(); + + if (['-'] === $filenames) { + return $this->display($io, [$this->validate(file_get_contents('php://stdin'))]); + } + + // @deprecated to be removed in 5.0 + if (!$filenames) { + if (0 !== ftell(STDIN)) { + throw new RuntimeException('Please provide a filename or pipe file content to STDIN.'); + } + + @trigger_error('Piping content from STDIN to the "lint:xliff" command without passing the dash symbol "-" as argument is deprecated since Symfony 4.4.', E_USER_DEPRECATED); + + return $this->display($io, [$this->validate(file_get_contents('php://stdin'))]); + } + + $filesInfo = []; + foreach ($filenames as $filename) { + if (!$this->isReadable($filename)) { + throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename)); + } + + foreach ($this->getFiles($filename) as $file) { + $filesInfo[] = $this->validate(file_get_contents($file), $file); + } + } + + return $this->display($io, $filesInfo); + } + + private function validate(string $content, string $file = null): array + { + $errors = []; + + // Avoid: Warning DOMDocument::loadXML(): Empty string supplied as input + if ('' === trim($content)) { + return ['file' => $file, 'valid' => true]; + } + + $internal = libxml_use_internal_errors(true); + + $document = new \DOMDocument(); + $document->loadXML($content); + + if (null !== $targetLanguage = $this->getTargetLanguageFromFile($document)) { + $normalizedLocale = preg_quote(str_replace('-', '_', $targetLanguage), '/'); + // strict file names require translation files to be named '____.locale.xlf' + // otherwise, both '____.locale.xlf' and 'locale.____.xlf' are allowed + // also, the regexp matching must be case-insensitive, as defined for 'target-language' values + // http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#target-language + $expectedFilenamePattern = $this->requireStrictFileNames ? sprintf('/^.*\.(?i:%s)\.(?:xlf|xliff)/', $normalizedLocale) : sprintf('/^(?:.*\.(?i:%s)|(?i:%s)\..*)\.(?:xlf|xliff)/', $normalizedLocale, $normalizedLocale); + + if (0 === preg_match($expectedFilenamePattern, basename($file))) { + $errors[] = [ + 'line' => -1, + 'column' => -1, + 'message' => sprintf('There is a mismatch between the language included in the file name ("%s") and the "%s" value used in the "target-language" attribute of the file.', basename($file), $targetLanguage), + ]; + } + } + + foreach (XliffUtils::validateSchema($document) as $xmlError) { + $errors[] = [ + 'line' => $xmlError['line'], + 'column' => $xmlError['column'], + 'message' => $xmlError['message'], + ]; + } + + libxml_clear_errors(); + libxml_use_internal_errors($internal); + + return ['file' => $file, 'valid' => 0 === \count($errors), 'messages' => $errors]; + } + + private function display(SymfonyStyle $io, array $files) + { + switch ($this->format) { + case 'txt': + return $this->displayTxt($io, $files); + case 'json': + return $this->displayJson($io, $files); + default: + throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format)); + } + } + + private function displayTxt(SymfonyStyle $io, array $filesInfo) + { + $countFiles = \count($filesInfo); + $erroredFiles = 0; + + foreach ($filesInfo as $info) { + if ($info['valid'] && $this->displayCorrectFiles) { + $io->comment('OK'.($info['file'] ? sprintf(' in %s', $info['file']) : '')); + } elseif (!$info['valid']) { + ++$erroredFiles; + $io->text(' ERROR '.($info['file'] ? sprintf(' in %s', $info['file']) : '')); + $io->listing(array_map(function ($error) { + // general document errors have a '-1' line number + return -1 === $error['line'] ? $error['message'] : sprintf('Line %d, Column %d: %s', $error['line'], $error['column'], $error['message']); + }, $info['messages'])); + } + } + + if (0 === $erroredFiles) { + $io->success(sprintf('All %d XLIFF files contain valid syntax.', $countFiles)); + } else { + $io->warning(sprintf('%d XLIFF files have valid syntax and %d contain errors.', $countFiles - $erroredFiles, $erroredFiles)); + } + + return min($erroredFiles, 1); + } + + private function displayJson(SymfonyStyle $io, array $filesInfo) + { + $errors = 0; + + array_walk($filesInfo, function (&$v) use (&$errors) { + $v['file'] = (string) $v['file']; + if (!$v['valid']) { + ++$errors; + } + }); + + $io->writeln(json_encode($filesInfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + + return min($errors, 1); + } + + private function getFiles(string $fileOrDirectory) + { + if (is_file($fileOrDirectory)) { + yield new \SplFileInfo($fileOrDirectory); + + return; + } + + foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) { + if (!\in_array($file->getExtension(), ['xlf', 'xliff'])) { + continue; + } + + yield $file; + } + } + + private function getDirectoryIterator(string $directory) + { + $default = function ($directory) { + return new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), + \RecursiveIteratorIterator::LEAVES_ONLY + ); + }; + + if (null !== $this->directoryIteratorProvider) { + return ($this->directoryIteratorProvider)($directory, $default); + } + + return $default($directory); + } + + private function isReadable(string $fileOrDirectory) + { + $default = function ($fileOrDirectory) { + return is_readable($fileOrDirectory); + }; + + if (null !== $this->isReadableProvider) { + return ($this->isReadableProvider)($fileOrDirectory, $default); + } + + return $default($fileOrDirectory); + } + + private function getTargetLanguageFromFile(\DOMDocument $xliffContents): ?string + { + foreach ($xliffContents->getElementsByTagName('file')[0]->attributes ?? [] as $attribute) { + if ('target-language' === $attribute->nodeName) { + return $attribute->nodeValue; + } + } + + return null; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/DataCollector/TranslationDataCollector.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/DataCollector/TranslationDataCollector.php new file mode 100644 index 0000000..9b6da11 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/DataCollector/TranslationDataCollector.php @@ -0,0 +1,174 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DataCollector; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\DataCollector; +use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; +use Symfony\Component\Translation\DataCollectorTranslator; +use Symfony\Component\VarDumper\Cloner\Data; + +/** + * @author Abdellatif Ait boudad + * + * @final since Symfony 4.4 + */ +class TranslationDataCollector extends DataCollector implements LateDataCollectorInterface +{ + private $translator; + + public function __construct(DataCollectorTranslator $translator) + { + $this->translator = $translator; + } + + /** + * {@inheritdoc} + */ + public function lateCollect() + { + $messages = $this->sanitizeCollectedMessages($this->translator->getCollectedMessages()); + + $this->data += $this->computeCount($messages); + $this->data['messages'] = $messages; + + $this->data = $this->cloneVar($this->data); + } + + /** + * {@inheritdoc} + * + * @param \Throwable|null $exception + */ + public function collect(Request $request, Response $response/*, \Throwable $exception = null*/) + { + $this->data['locale'] = $this->translator->getLocale(); + $this->data['fallback_locales'] = $this->translator->getFallbackLocales(); + } + + /** + * {@inheritdoc} + */ + public function reset() + { + $this->data = []; + } + + /** + * @return array|Data + */ + public function getMessages() + { + return isset($this->data['messages']) ? $this->data['messages'] : []; + } + + /** + * @return int + */ + public function getCountMissings() + { + return isset($this->data[DataCollectorTranslator::MESSAGE_MISSING]) ? $this->data[DataCollectorTranslator::MESSAGE_MISSING] : 0; + } + + /** + * @return int + */ + public function getCountFallbacks() + { + return isset($this->data[DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK]) ? $this->data[DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK] : 0; + } + + /** + * @return int + */ + public function getCountDefines() + { + return isset($this->data[DataCollectorTranslator::MESSAGE_DEFINED]) ? $this->data[DataCollectorTranslator::MESSAGE_DEFINED] : 0; + } + + public function getLocale() + { + return !empty($this->data['locale']) ? $this->data['locale'] : null; + } + + /** + * @internal since Symfony 4.2 + */ + public function getFallbackLocales() + { + return (isset($this->data['fallback_locales']) && \count($this->data['fallback_locales']) > 0) ? $this->data['fallback_locales'] : []; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'translation'; + } + + private function sanitizeCollectedMessages(array $messages) + { + $result = []; + foreach ($messages as $key => $message) { + $messageId = $message['locale'].$message['domain'].$message['id']; + + if (!isset($result[$messageId])) { + $message['count'] = 1; + $message['parameters'] = !empty($message['parameters']) ? [$message['parameters']] : []; + $messages[$key]['translation'] = $this->sanitizeString($message['translation']); + $result[$messageId] = $message; + } else { + if (!empty($message['parameters'])) { + $result[$messageId]['parameters'][] = $message['parameters']; + } + + ++$result[$messageId]['count']; + } + + unset($messages[$key]); + } + + return $result; + } + + private function computeCount(array $messages) + { + $count = [ + DataCollectorTranslator::MESSAGE_DEFINED => 0, + DataCollectorTranslator::MESSAGE_MISSING => 0, + DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK => 0, + ]; + + foreach ($messages as $message) { + ++$count[$message['state']]; + } + + return $count; + } + + private function sanitizeString(string $string, int $length = 80) + { + $string = trim(preg_replace('/\s+/', ' ', $string)); + + if (false !== $encoding = mb_detect_encoding($string, null, true)) { + if (mb_strlen($string, $encoding) > $length) { + return mb_substr($string, 0, $length - 3, $encoding).'...'; + } + } elseif (\strlen($string) > $length) { + return substr($string, 0, $length - 3).'...'; + } + + return $string; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/DataCollectorTranslator.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/DataCollectorTranslator.php new file mode 100644 index 0000000..94b9e3e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/DataCollectorTranslator.php @@ -0,0 +1,182 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * @author Abdellatif Ait boudad + */ +class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorInterface, TranslatorBagInterface, WarmableInterface +{ + const MESSAGE_DEFINED = 0; + const MESSAGE_MISSING = 1; + const MESSAGE_EQUALS_FALLBACK = 2; + + /** + * @var TranslatorInterface|TranslatorBagInterface + */ + private $translator; + + private $messages = []; + + /** + * @param TranslatorInterface $translator The translator must implement TranslatorBagInterface + */ + public function __construct($translator) + { + if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) { + throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be an instance of "%s", "%s" given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator))); + } + if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) { + throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', \get_class($translator))); + } + + $this->translator = $translator; + } + + /** + * {@inheritdoc} + */ + public function trans($id, array $parameters = [], $domain = null, $locale = null) + { + $trans = $this->translator->trans($id, $parameters, $domain, $locale); + $this->collectMessage($locale, $domain, $id, $trans, $parameters); + + return $trans; + } + + /** + * {@inheritdoc} + * + * @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter + */ + public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null) + { + if ($this->translator instanceof TranslatorInterface) { + $trans = $this->translator->trans($id, ['%count%' => $number] + $parameters, $domain, $locale); + } else { + $trans = $this->translator->transChoice($id, $number, $parameters, $domain, $locale); + } + + $this->collectMessage($locale, $domain, $id, $trans, ['%count%' => $number] + $parameters); + + return $trans; + } + + /** + * {@inheritdoc} + */ + public function setLocale($locale) + { + $this->translator->setLocale($locale); + } + + /** + * {@inheritdoc} + */ + public function getLocale() + { + return $this->translator->getLocale(); + } + + /** + * {@inheritdoc} + */ + public function getCatalogue($locale = null) + { + return $this->translator->getCatalogue($locale); + } + + /** + * {@inheritdoc} + */ + public function warmUp($cacheDir) + { + if ($this->translator instanceof WarmableInterface) { + $this->translator->warmUp($cacheDir); + } + } + + /** + * Gets the fallback locales. + * + * @return array The fallback locales + */ + public function getFallbackLocales() + { + if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) { + return $this->translator->getFallbackLocales(); + } + + return []; + } + + /** + * Passes through all unknown calls onto the translator object. + */ + public function __call($method, $args) + { + return $this->translator->{$method}(...$args); + } + + /** + * @return array + */ + public function getCollectedMessages() + { + return $this->messages; + } + + private function collectMessage(?string $locale, ?string $domain, ?string $id, string $translation, ?array $parameters = []) + { + if (null === $domain) { + $domain = 'messages'; + } + + $id = (string) $id; + $catalogue = $this->translator->getCatalogue($locale); + $locale = $catalogue->getLocale(); + $fallbackLocale = null; + if ($catalogue->defines($id, $domain)) { + $state = self::MESSAGE_DEFINED; + } elseif ($catalogue->has($id, $domain)) { + $state = self::MESSAGE_EQUALS_FALLBACK; + + $fallbackCatalogue = $catalogue->getFallbackCatalogue(); + while ($fallbackCatalogue) { + if ($fallbackCatalogue->defines($id, $domain)) { + $fallbackLocale = $fallbackCatalogue->getLocale(); + break; + } + $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue(); + } + } else { + $state = self::MESSAGE_MISSING; + } + + $this->messages[] = [ + 'locale' => $locale, + 'fallbackLocale' => $fallbackLocale, + 'domain' => $domain, + 'id' => $id, + 'translation' => $translation, + 'parameters' => $parameters, + 'state' => $state, + 'transChoiceNumber' => isset($parameters['%count%']) && is_numeric($parameters['%count%']) ? $parameters['%count%'] : null, + ]; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php new file mode 100644 index 0000000..930f36d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Adds tagged translation.formatter services to translation writer. + */ +class TranslationDumperPass implements CompilerPassInterface +{ + private $writerServiceId; + private $dumperTag; + + public function __construct(string $writerServiceId = 'translation.writer', string $dumperTag = 'translation.dumper') + { + $this->writerServiceId = $writerServiceId; + $this->dumperTag = $dumperTag; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->writerServiceId)) { + return; + } + + $definition = $container->getDefinition($this->writerServiceId); + + foreach ($container->findTaggedServiceIds($this->dumperTag, true) as $id => $attributes) { + $definition->addMethodCall('addDumper', [$attributes[0]['alias'], new Reference($id)]); + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php new file mode 100644 index 0000000..d08b2ba --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Adds tagged translation.extractor services to translation extractor. + */ +class TranslationExtractorPass implements CompilerPassInterface +{ + private $extractorServiceId; + private $extractorTag; + + public function __construct(string $extractorServiceId = 'translation.extractor', string $extractorTag = 'translation.extractor') + { + $this->extractorServiceId = $extractorServiceId; + $this->extractorTag = $extractorTag; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->extractorServiceId)) { + return; + } + + $definition = $container->getDefinition($this->extractorServiceId); + + foreach ($container->findTaggedServiceIds($this->extractorTag, true) as $id => $attributes) { + if (!isset($attributes[0]['alias'])) { + throw new RuntimeException(sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id)); + } + + $definition->addMethodCall('addExtractor', [$attributes[0]['alias'], new Reference($id)]); + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslatorPass.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslatorPass.php new file mode 100644 index 0000000..ed4a840 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslatorPass.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +class TranslatorPass implements CompilerPassInterface +{ + private $translatorServiceId; + private $readerServiceId; + private $loaderTag; + private $debugCommandServiceId; + private $updateCommandServiceId; + + public function __construct(string $translatorServiceId = 'translator.default', string $readerServiceId = 'translation.reader', string $loaderTag = 'translation.loader', string $debugCommandServiceId = 'console.command.translation_debug', string $updateCommandServiceId = 'console.command.translation_update') + { + $this->translatorServiceId = $translatorServiceId; + $this->readerServiceId = $readerServiceId; + $this->loaderTag = $loaderTag; + $this->debugCommandServiceId = $debugCommandServiceId; + $this->updateCommandServiceId = $updateCommandServiceId; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->translatorServiceId)) { + return; + } + + $loaders = []; + $loaderRefs = []; + foreach ($container->findTaggedServiceIds($this->loaderTag, true) as $id => $attributes) { + $loaderRefs[$id] = new Reference($id); + $loaders[$id][] = $attributes[0]['alias']; + if (isset($attributes[0]['legacy-alias'])) { + $loaders[$id][] = $attributes[0]['legacy-alias']; + } + } + + if ($container->hasDefinition($this->readerServiceId)) { + $definition = $container->getDefinition($this->readerServiceId); + foreach ($loaders as $id => $formats) { + foreach ($formats as $format) { + $definition->addMethodCall('addLoader', [$format, $loaderRefs[$id]]); + } + } + } + + $container + ->findDefinition($this->translatorServiceId) + ->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs)) + ->replaceArgument(3, $loaders) + ; + + if (!$container->hasParameter('twig.default_path')) { + return; + } + + $paths = array_keys($container->getDefinition('twig.template_iterator')->getArgument(2)); + if ($container->hasDefinition($this->debugCommandServiceId)) { + $definition = $container->getDefinition($this->debugCommandServiceId); + $definition->replaceArgument(4, $container->getParameter('twig.default_path')); + + if (\count($definition->getArguments()) > 6) { + $definition->replaceArgument(6, $paths); + } + } + if ($container->hasDefinition($this->updateCommandServiceId)) { + $definition = $container->getDefinition($this->updateCommandServiceId); + $definition->replaceArgument(5, $container->getParameter('twig.default_path')); + + if (\count($definition->getArguments()) > 7) { + $definition->replaceArgument(7, $paths); + } + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php new file mode 100644 index 0000000..8ff2587 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php @@ -0,0 +1,144 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ServiceLocator; + +/** + * @author Yonel Ceruto + */ +class TranslatorPathsPass extends AbstractRecursivePass +{ + private $translatorServiceId; + private $debugCommandServiceId; + private $updateCommandServiceId; + private $resolverServiceId; + private $level = 0; + private $paths = []; + private $definitions = []; + private $controllers = []; + + public function __construct(string $translatorServiceId = 'translator', string $debugCommandServiceId = 'console.command.translation_debug', string $updateCommandServiceId = 'console.command.translation_update', string $resolverServiceId = 'argument_resolver.service') + { + $this->translatorServiceId = $translatorServiceId; + $this->debugCommandServiceId = $debugCommandServiceId; + $this->updateCommandServiceId = $updateCommandServiceId; + $this->resolverServiceId = $resolverServiceId; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->translatorServiceId)) { + return; + } + + foreach ($this->findControllerArguments($container) as $controller => $argument) { + $id = substr($controller, 0, strpos($controller, ':') ?: \strlen($controller)); + if ($container->hasDefinition($id)) { + list($locatorRef) = $argument->getValues(); + $this->controllers[(string) $locatorRef][$container->getDefinition($id)->getClass()] = true; + } + } + + try { + parent::process($container); + + $paths = []; + foreach ($this->paths as $class => $_) { + if (($r = $container->getReflectionClass($class)) && !$r->isInterface()) { + $paths[] = $r->getFileName(); + } + } + if ($paths) { + if ($container->hasDefinition($this->debugCommandServiceId)) { + $definition = $container->getDefinition($this->debugCommandServiceId); + $definition->replaceArgument(6, array_merge($definition->getArgument(6), $paths)); + } + if ($container->hasDefinition($this->updateCommandServiceId)) { + $definition = $container->getDefinition($this->updateCommandServiceId); + $definition->replaceArgument(7, array_merge($definition->getArgument(7), $paths)); + } + } + } finally { + $this->level = 0; + $this->paths = []; + $this->definitions = []; + } + } + + protected function processValue($value, $isRoot = false) + { + if ($value instanceof Reference) { + if ((string) $value === $this->translatorServiceId) { + for ($i = $this->level - 1; $i >= 0; --$i) { + $class = $this->definitions[$i]->getClass(); + + if (ServiceLocator::class === $class) { + if (!isset($this->controllers[$this->currentId])) { + continue; + } + foreach ($this->controllers[$this->currentId] as $class => $_) { + $this->paths[$class] = true; + } + } else { + $this->paths[$class] = true; + } + + break; + } + } + + return $value; + } + + if ($value instanceof Definition) { + $this->definitions[$this->level++] = $value; + $value = parent::processValue($value, $isRoot); + unset($this->definitions[--$this->level]); + + return $value; + } + + return parent::processValue($value, $isRoot); + } + + private function findControllerArguments(ContainerBuilder $container): array + { + if ($container->hasDefinition($this->resolverServiceId)) { + $argument = $container->getDefinition($this->resolverServiceId)->getArgument(0); + if ($argument instanceof Reference) { + $argument = $container->getDefinition($argument); + } + + return $argument->getArgument(0); + } + + if ($container->hasDefinition('debug.'.$this->resolverServiceId)) { + $argument = $container->getDefinition('debug.'.$this->resolverServiceId)->getArgument(0); + if ($argument instanceof Reference) { + $argument = $container->getDefinition($argument); + } + $argument = $argument->getArgument(0); + if ($argument instanceof Reference) { + $argument = $container->getDefinition($argument); + } + + return $argument->getArgument(0); + } + + return []; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/CsvFileDumper.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/CsvFileDumper.php new file mode 100644 index 0000000..bfa8db6 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/CsvFileDumper.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * CsvFileDumper generates a csv formatted string representation of a message catalogue. + * + * @author Stealth35 + */ +class CsvFileDumper extends FileDumper +{ + private $delimiter = ';'; + private $enclosure = '"'; + + /** + * {@inheritdoc} + */ + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []) + { + $handle = fopen('php://memory', 'r+b'); + + foreach ($messages->all($domain) as $source => $target) { + fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure); + } + + rewind($handle); + $output = stream_get_contents($handle); + fclose($handle); + + return $output; + } + + /** + * Sets the delimiter and escape character for CSV. + * + * @param string $delimiter Delimiter character + * @param string $enclosure Enclosure character + */ + public function setCsvControl($delimiter = ';', $enclosure = '"') + { + $this->delimiter = $delimiter; + $this->enclosure = $enclosure; + } + + /** + * {@inheritdoc} + */ + protected function getExtension() + { + return 'csv'; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/DumperInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/DumperInterface.php new file mode 100644 index 0000000..445b701 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/DumperInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * DumperInterface is the interface implemented by all translation dumpers. + * There is no common option. + * + * @author Michel Salib + */ +interface DumperInterface +{ + /** + * Dumps the message catalogue. + * + * @param array $options Options that are used by the dumper + */ + public function dump(MessageCatalogue $messages, $options = []); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/FileDumper.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/FileDumper.php new file mode 100644 index 0000000..2009c53 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/FileDumper.php @@ -0,0 +1,130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\RuntimeException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s). + * + * Options: + * - path (mandatory): the directory where the files should be saved + * + * @author Michel Salib + */ +abstract class FileDumper implements DumperInterface +{ + /** + * A template for the relative paths to files. + * + * @var string + */ + protected $relativePathTemplate = '%domain%.%locale%.%extension%'; + + /** + * Sets the template for the relative paths to files. + * + * @param string $relativePathTemplate A template for the relative paths to files + */ + public function setRelativePathTemplate($relativePathTemplate) + { + $this->relativePathTemplate = $relativePathTemplate; + } + + /** + * Sets backup flag. + * + * @param bool $backup + * + * @deprecated since Symfony 4.1 + */ + public function setBackup($backup) + { + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1.', __METHOD__), E_USER_DEPRECATED); + + if (false !== $backup) { + throw new \LogicException('The backup feature is no longer supported.'); + } + } + + /** + * {@inheritdoc} + */ + public function dump(MessageCatalogue $messages, $options = []) + { + if (!\array_key_exists('path', $options)) { + throw new InvalidArgumentException('The file dumper needs a path option.'); + } + + // save a file for each domain + foreach ($messages->getDomains() as $domain) { + $fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale()); + if (!file_exists($fullpath)) { + $directory = \dirname($fullpath); + if (!file_exists($directory) && !@mkdir($directory, 0777, true)) { + throw new RuntimeException(sprintf('Unable to create directory "%s".', $directory)); + } + } + + $intlDomain = $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX; + $intlMessages = $messages->all($intlDomain); + + if ($intlMessages) { + $intlPath = $options['path'].'/'.$this->getRelativePath($intlDomain, $messages->getLocale()); + file_put_contents($intlPath, $this->formatCatalogue($messages, $intlDomain, $options)); + + $messages->replace([], $intlDomain); + + try { + if ($messages->all($domain)) { + file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options)); + } + continue; + } finally { + $messages->replace($intlMessages, $intlDomain); + } + } + + file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options)); + } + } + + /** + * Transforms a domain of a message catalogue to its string representation. + * + * @param string $domain + * + * @return string representation + */ + abstract public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []); + + /** + * Gets the file extension of the dumper. + * + * @return string file extension + */ + abstract protected function getExtension(); + + /** + * Gets the relative file path using the template. + */ + private function getRelativePath(string $domain, string $locale): string + { + return strtr($this->relativePathTemplate, [ + '%domain%' => $domain, + '%locale%' => $locale, + '%extension%' => $this->getExtension(), + ]); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/IcuResFileDumper.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/IcuResFileDumper.php new file mode 100644 index 0000000..829e0d0 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/IcuResFileDumper.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue. + * + * @author Stealth35 + */ +class IcuResFileDumper extends FileDumper +{ + /** + * {@inheritdoc} + */ + protected $relativePathTemplate = '%domain%/%locale%.%extension%'; + + /** + * {@inheritdoc} + */ + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []) + { + $data = $indexes = $resources = ''; + + foreach ($messages->all($domain) as $source => $target) { + $indexes .= pack('v', \strlen($data) + 28); + $data .= $source."\0"; + } + + $data .= $this->writePadding($data); + + $keyTop = $this->getPosition($data); + + foreach ($messages->all($domain) as $source => $target) { + $resources .= pack('V', $this->getPosition($data)); + + $data .= pack('V', \strlen($target)) + .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8') + .$this->writePadding($data) + ; + } + + $resOffset = $this->getPosition($data); + + $data .= pack('v', \count($messages->all($domain))) + .$indexes + .$this->writePadding($data) + .$resources + ; + + $bundleTop = $this->getPosition($data); + + $root = pack('V7', + $resOffset + (2 << 28), // Resource Offset + Resource Type + 6, // Index length + $keyTop, // Index keys top + $bundleTop, // Index resources top + $bundleTop, // Index bundle top + \count($messages->all($domain)), // Index max table length + 0 // Index attributes + ); + + $header = pack('vC2v4C12@32', + 32, // Header size + 0xDA, 0x27, // Magic number 1 and 2 + 20, 0, 0, 2, // Rest of the header, ..., Size of a char + 0x52, 0x65, 0x73, 0x42, // Data format identifier + 1, 2, 0, 0, // Data version + 1, 4, 0, 0 // Unicode version + ); + + return $header.$root.$data; + } + + private function writePadding(string $data): ?string + { + $padding = \strlen($data) % 4; + + return $padding ? str_repeat("\xAA", 4 - $padding) : null; + } + + private function getPosition(string $data) + { + return (\strlen($data) + 28) / 4; + } + + /** + * {@inheritdoc} + */ + protected function getExtension() + { + return 'res'; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/IniFileDumper.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/IniFileDumper.php new file mode 100644 index 0000000..45ff961 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/IniFileDumper.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * IniFileDumper generates an ini formatted string representation of a message catalogue. + * + * @author Stealth35 + */ +class IniFileDumper extends FileDumper +{ + /** + * {@inheritdoc} + */ + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []) + { + $output = ''; + + foreach ($messages->all($domain) as $source => $target) { + $escapeTarget = str_replace('"', '\"', $target); + $output .= $source.'="'.$escapeTarget."\"\n"; + } + + return $output; + } + + /** + * {@inheritdoc} + */ + protected function getExtension() + { + return 'ini'; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/JsonFileDumper.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/JsonFileDumper.php new file mode 100644 index 0000000..2af8231 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/JsonFileDumper.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * JsonFileDumper generates an json formatted string representation of a message catalogue. + * + * @author singles + */ +class JsonFileDumper extends FileDumper +{ + /** + * {@inheritdoc} + */ + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []) + { + $flags = $options['json_encoding'] ?? JSON_PRETTY_PRINT; + + return json_encode($messages->all($domain), $flags); + } + + /** + * {@inheritdoc} + */ + protected function getExtension() + { + return 'json'; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/MoFileDumper.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/MoFileDumper.php new file mode 100644 index 0000000..5a96dac --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/MoFileDumper.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\Loader\MoFileLoader; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * MoFileDumper generates a gettext formatted string representation of a message catalogue. + * + * @author Stealth35 + */ +class MoFileDumper extends FileDumper +{ + /** + * {@inheritdoc} + */ + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []) + { + $sources = $targets = $sourceOffsets = $targetOffsets = ''; + $offsets = []; + $size = 0; + + foreach ($messages->all($domain) as $source => $target) { + $offsets[] = array_map('strlen', [$sources, $source, $targets, $target]); + $sources .= "\0".$source; + $targets .= "\0".$target; + ++$size; + } + + $header = [ + 'magicNumber' => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC, + 'formatRevision' => 0, + 'count' => $size, + 'offsetId' => MoFileLoader::MO_HEADER_SIZE, + 'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size), + 'sizeHashes' => 0, + 'offsetHashes' => MoFileLoader::MO_HEADER_SIZE + (16 * $size), + ]; + + $sourcesSize = \strlen($sources); + $sourcesStart = $header['offsetHashes'] + 1; + + foreach ($offsets as $offset) { + $sourceOffsets .= $this->writeLong($offset[1]) + .$this->writeLong($offset[0] + $sourcesStart); + $targetOffsets .= $this->writeLong($offset[3]) + .$this->writeLong($offset[2] + $sourcesStart + $sourcesSize); + } + + $output = implode('', array_map([$this, 'writeLong'], $header)) + .$sourceOffsets + .$targetOffsets + .$sources + .$targets + ; + + return $output; + } + + /** + * {@inheritdoc} + */ + protected function getExtension() + { + return 'mo'; + } + + private function writeLong($str): string + { + return pack('V*', $str); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/PhpFileDumper.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/PhpFileDumper.php new file mode 100644 index 0000000..e77afc2 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/PhpFileDumper.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * PhpFileDumper generates PHP files from a message catalogue. + * + * @author Michel Salib + */ +class PhpFileDumper extends FileDumper +{ + /** + * {@inheritdoc} + */ + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []) + { + return "all($domain), true).";\n"; + } + + /** + * {@inheritdoc} + */ + protected function getExtension() + { + return 'php'; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/PoFileDumper.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/PoFileDumper.php new file mode 100644 index 0000000..2cc9e88 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/PoFileDumper.php @@ -0,0 +1,137 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * PoFileDumper generates a gettext formatted string representation of a message catalogue. + * + * @author Stealth35 + */ +class PoFileDumper extends FileDumper +{ + /** + * {@inheritdoc} + */ + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []) + { + $output = 'msgid ""'."\n"; + $output .= 'msgstr ""'."\n"; + $output .= '"Content-Type: text/plain; charset=UTF-8\n"'."\n"; + $output .= '"Content-Transfer-Encoding: 8bit\n"'."\n"; + $output .= '"Language: '.$messages->getLocale().'\n"'."\n"; + $output .= "\n"; + + $newLine = false; + foreach ($messages->all($domain) as $source => $target) { + if ($newLine) { + $output .= "\n"; + } else { + $newLine = true; + } + $metadata = $messages->getMetadata($source, $domain); + + if (isset($metadata['comments'])) { + $output .= $this->formatComments($metadata['comments']); + } + if (isset($metadata['flags'])) { + $output .= $this->formatComments(implode(',', (array) $metadata['flags']), ','); + } + if (isset($metadata['sources'])) { + $output .= $this->formatComments(implode(' ', (array) $metadata['sources']), ':'); + } + + $sourceRules = $this->getStandardRules($source); + $targetRules = $this->getStandardRules($target); + if (2 == \count($sourceRules) && $targetRules !== []) { + $output .= sprintf('msgid "%s"'."\n", $this->escape($sourceRules[0])); + $output .= sprintf('msgid_plural "%s"'."\n", $this->escape($sourceRules[1])); + foreach ($targetRules as $i => $targetRule) { + $output .= sprintf('msgstr[%d] "%s"'."\n", $i, $this->escape($targetRule)); + } + } else { + $output .= sprintf('msgid "%s"'."\n", $this->escape($source)); + $output .= sprintf('msgstr "%s"'."\n", $this->escape($target)); + } + } + + return $output; + } + + private function getStandardRules(string $id) + { + // Partly copied from TranslatorTrait::trans. + $parts = []; + if (preg_match('/^\|++$/', $id)) { + $parts = explode('|', $id); + } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) { + $parts = $matches[0]; + } + + $intervalRegexp = <<<'EOF' +/^(?P + ({\s* + (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*) + \s*}) + + | + + (?P[\[\]]) + \s* + (?P-Inf|\-?\d+(\.\d+)?) + \s*,\s* + (?P\+?Inf|\-?\d+(\.\d+)?) + \s* + (?P[\[\]]) +)\s*(?P.*?)$/xs +EOF; + + $standardRules = []; + foreach ($parts as $part) { + $part = trim(str_replace('||', '|', $part)); + + if (preg_match($intervalRegexp, $part)) { + // Explicit rule is not a standard rule. + return []; + } else { + $standardRules[] = $part; + } + } + + return $standardRules; + } + + /** + * {@inheritdoc} + */ + protected function getExtension() + { + return 'po'; + } + + private function escape(string $str): string + { + return addcslashes($str, "\0..\37\42\134"); + } + + private function formatComments($comments, string $prefix = ''): ?string + { + $output = null; + + foreach ((array) $comments as $comment) { + $output .= sprintf('#%s %s'."\n", $prefix, $comment); + } + + return $output; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/QtFileDumper.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/QtFileDumper.php new file mode 100644 index 0000000..79a64b2 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/QtFileDumper.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * QtFileDumper generates ts files from a message catalogue. + * + * @author Benjamin Eberlei + */ +class QtFileDumper extends FileDumper +{ + /** + * {@inheritdoc} + */ + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []) + { + $dom = new \DOMDocument('1.0', 'utf-8'); + $dom->formatOutput = true; + $ts = $dom->appendChild($dom->createElement('TS')); + $context = $ts->appendChild($dom->createElement('context')); + $context->appendChild($dom->createElement('name', $domain)); + + foreach ($messages->all($domain) as $source => $target) { + $message = $context->appendChild($dom->createElement('message')); + $metadata = $messages->getMetadata($source, $domain); + if (isset($metadata['sources'])) { + foreach ((array) $metadata['sources'] as $location) { + $loc = explode(':', $location, 2); + $location = $message->appendChild($dom->createElement('location')); + $location->setAttribute('filename', $loc[0]); + if (isset($loc[1])) { + $location->setAttribute('line', $loc[1]); + } + } + } + $message->appendChild($dom->createElement('source', $source)); + $message->appendChild($dom->createElement('translation', $target)); + } + + return $dom->saveXML(); + } + + /** + * {@inheritdoc} + */ + protected function getExtension() + { + return 'ts'; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/XliffFileDumper.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/XliffFileDumper.php new file mode 100644 index 0000000..dd9d788 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/XliffFileDumper.php @@ -0,0 +1,203 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * XliffFileDumper generates xliff files from a message catalogue. + * + * @author Michel Salib + */ +class XliffFileDumper extends FileDumper +{ + /** + * {@inheritdoc} + */ + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []) + { + $xliffVersion = '1.2'; + if (\array_key_exists('xliff_version', $options)) { + $xliffVersion = $options['xliff_version']; + } + + if (\array_key_exists('default_locale', $options)) { + $defaultLocale = $options['default_locale']; + } else { + $defaultLocale = \Locale::getDefault(); + } + + if ('1.2' === $xliffVersion) { + return $this->dumpXliff1($defaultLocale, $messages, $domain, $options); + } + if ('2.0' === $xliffVersion) { + return $this->dumpXliff2($defaultLocale, $messages, $domain); + } + + throw new InvalidArgumentException(sprintf('No support implemented for dumping XLIFF version "%s".', $xliffVersion)); + } + + /** + * {@inheritdoc} + */ + protected function getExtension() + { + return 'xlf'; + } + + private function dumpXliff1(string $defaultLocale, MessageCatalogue $messages, ?string $domain, array $options = []) + { + $toolInfo = ['tool-id' => 'symfony', 'tool-name' => 'Symfony']; + if (\array_key_exists('tool_info', $options)) { + $toolInfo = array_merge($toolInfo, $options['tool_info']); + } + + $dom = new \DOMDocument('1.0', 'utf-8'); + $dom->formatOutput = true; + + $xliff = $dom->appendChild($dom->createElement('xliff')); + $xliff->setAttribute('version', '1.2'); + $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2'); + + $xliffFile = $xliff->appendChild($dom->createElement('file')); + $xliffFile->setAttribute('source-language', str_replace('_', '-', $defaultLocale)); + $xliffFile->setAttribute('target-language', str_replace('_', '-', $messages->getLocale())); + $xliffFile->setAttribute('datatype', 'plaintext'); + $xliffFile->setAttribute('original', 'file.ext'); + + $xliffHead = $xliffFile->appendChild($dom->createElement('header')); + $xliffTool = $xliffHead->appendChild($dom->createElement('tool')); + foreach ($toolInfo as $id => $value) { + $xliffTool->setAttribute($id, $value); + } + + $xliffBody = $xliffFile->appendChild($dom->createElement('body')); + foreach ($messages->all($domain) as $source => $target) { + $translation = $dom->createElement('trans-unit'); + + $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); + $translation->setAttribute('resname', $source); + + $s = $translation->appendChild($dom->createElement('source')); + $s->appendChild($dom->createTextNode($source)); + + // Does the target contain characters requiring a CDATA section? + $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target); + + $targetElement = $dom->createElement('target'); + $metadata = $messages->getMetadata($source, $domain); + if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) { + foreach ($metadata['target-attributes'] as $name => $value) { + $targetElement->setAttribute($name, $value); + } + } + $t = $translation->appendChild($targetElement); + $t->appendChild($text); + + if ($this->hasMetadataArrayInfo('notes', $metadata)) { + foreach ($metadata['notes'] as $note) { + if (!isset($note['content'])) { + continue; + } + + $n = $translation->appendChild($dom->createElement('note')); + $n->appendChild($dom->createTextNode($note['content'])); + + if (isset($note['priority'])) { + $n->setAttribute('priority', $note['priority']); + } + + if (isset($note['from'])) { + $n->setAttribute('from', $note['from']); + } + } + } + + $xliffBody->appendChild($translation); + } + + return $dom->saveXML(); + } + + private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ?string $domain) + { + $dom = new \DOMDocument('1.0', 'utf-8'); + $dom->formatOutput = true; + + $xliff = $dom->appendChild($dom->createElement('xliff')); + $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:2.0'); + $xliff->setAttribute('version', '2.0'); + $xliff->setAttribute('srcLang', str_replace('_', '-', $defaultLocale)); + $xliff->setAttribute('trgLang', str_replace('_', '-', $messages->getLocale())); + + $xliffFile = $xliff->appendChild($dom->createElement('file')); + if (MessageCatalogue::INTL_DOMAIN_SUFFIX === substr($domain, -($suffixLength = \strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX)))) { + $xliffFile->setAttribute('id', substr($domain, 0, -$suffixLength).'.'.$messages->getLocale()); + } else { + $xliffFile->setAttribute('id', $domain.'.'.$messages->getLocale()); + } + + foreach ($messages->all($domain) as $source => $target) { + $translation = $dom->createElement('unit'); + $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); + $name = $source; + if (\strlen($source) > 80) { + $name = substr(md5($source), -7); + } + $translation->setAttribute('name', $name); + $metadata = $messages->getMetadata($source, $domain); + + // Add notes section + if ($this->hasMetadataArrayInfo('notes', $metadata)) { + $notesElement = $dom->createElement('notes'); + foreach ($metadata['notes'] as $note) { + $n = $dom->createElement('note'); + $n->appendChild($dom->createTextNode(isset($note['content']) ? $note['content'] : '')); + unset($note['content']); + + foreach ($note as $name => $value) { + $n->setAttribute($name, $value); + } + $notesElement->appendChild($n); + } + $translation->appendChild($notesElement); + } + + $segment = $translation->appendChild($dom->createElement('segment')); + + $s = $segment->appendChild($dom->createElement('source')); + $s->appendChild($dom->createTextNode($source)); + + // Does the target contain characters requiring a CDATA section? + $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target); + + $targetElement = $dom->createElement('target'); + if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) { + foreach ($metadata['target-attributes'] as $name => $value) { + $targetElement->setAttribute($name, $value); + } + } + $t = $segment->appendChild($targetElement); + $t->appendChild($text); + + $xliffFile->appendChild($translation); + } + + return $dom->saveXML(); + } + + private function hasMetadataArrayInfo(string $key, array $metadata = null): bool + { + return null !== $metadata && \array_key_exists($key, $metadata) && ($metadata[$key] instanceof \Traversable || \is_array($metadata[$key])); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/YamlFileDumper.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/YamlFileDumper.php new file mode 100644 index 0000000..d6e4af8 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Dumper/YamlFileDumper.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\Exception\LogicException; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Util\ArrayConverter; +use Symfony\Component\Yaml\Yaml; + +/** + * YamlFileDumper generates yaml files from a message catalogue. + * + * @author Michel Salib + */ +class YamlFileDumper extends FileDumper +{ + private $extension; + + public function __construct(string $extension = 'yml') + { + $this->extension = $extension; + } + + /** + * {@inheritdoc} + */ + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []) + { + if (!class_exists('Symfony\Component\Yaml\Yaml')) { + throw new LogicException('Dumping translations in the YAML format requires the Symfony Yaml component.'); + } + + $data = $messages->all($domain); + + if (isset($options['as_tree']) && $options['as_tree']) { + $data = ArrayConverter::expandToTree($data); + } + + if (isset($options['inline']) && ($inline = (int) $options['inline']) > 0) { + return Yaml::dump($data, $inline); + } + + return Yaml::dump($data); + } + + /** + * {@inheritdoc} + */ + protected function getExtension() + { + return $this->extension; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/ExceptionInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/ExceptionInterface.php new file mode 100644 index 0000000..8f9c54e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/ExceptionInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Exception interface for all exceptions thrown by the component. + * + * @author Fabien Potencier + */ +interface ExceptionInterface extends \Throwable +{ +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/InvalidArgumentException.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..90d0669 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/InvalidArgumentException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Base InvalidArgumentException for the Translation component. + * + * @author Abdellatif Ait boudad + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/InvalidResourceException.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/InvalidResourceException.php new file mode 100644 index 0000000..cf07943 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/InvalidResourceException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Thrown when a resource cannot be loaded. + * + * @author Fabien Potencier + */ +class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/LogicException.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/LogicException.php new file mode 100644 index 0000000..9019c7e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/LogicException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Base LogicException for Translation component. + * + * @author Abdellatif Ait boudad + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/NotFoundResourceException.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/NotFoundResourceException.php new file mode 100644 index 0000000..cff73ae --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/NotFoundResourceException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Thrown when a resource does not exist. + * + * @author Fabien Potencier + */ +class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/RuntimeException.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/RuntimeException.php new file mode 100644 index 0000000..dcd7940 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Exception/RuntimeException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Base RuntimeException for the Translation component. + * + * @author Abdellatif Ait boudad + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/AbstractFileExtractor.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/AbstractFileExtractor.php new file mode 100644 index 0000000..618df73 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/AbstractFileExtractor.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; + +/** + * Base class used by classes that extract translation messages from files. + * + * @author Marcos D. Sánchez + */ +abstract class AbstractFileExtractor +{ + /** + * @param string|iterable $resource Files, a file or a directory + * + * @return iterable + */ + protected function extractFiles($resource) + { + if (is_iterable($resource)) { + $files = []; + foreach ($resource as $file) { + if ($this->canBeExtracted($file)) { + $files[] = $this->toSplFileInfo($file); + } + } + } elseif (is_file($resource)) { + $files = $this->canBeExtracted($resource) ? [$this->toSplFileInfo($resource)] : []; + } else { + $files = $this->extractFromDirectory($resource); + } + + return $files; + } + + private function toSplFileInfo(string $file): \SplFileInfo + { + return new \SplFileInfo($file); + } + + /** + * @param string $file + * + * @return bool + * + * @throws InvalidArgumentException + */ + protected function isFile($file) + { + if (!is_file($file)) { + throw new InvalidArgumentException(sprintf('The "%s" file does not exist.', $file)); + } + + return true; + } + + /** + * @param string $file + * + * @return bool + */ + abstract protected function canBeExtracted($file); + + /** + * @param string|array $resource Files, a file or a directory + * + * @return iterable files to be extracted + */ + abstract protected function extractFromDirectory($resource); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/ChainExtractor.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/ChainExtractor.php new file mode 100644 index 0000000..2683f5d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/ChainExtractor.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * ChainExtractor extracts translation messages from template files. + * + * @author Michel Salib + */ +class ChainExtractor implements ExtractorInterface +{ + /** + * The extractors. + * + * @var ExtractorInterface[] + */ + private $extractors = []; + + /** + * Adds a loader to the translation extractor. + * + * @param string $format The format of the loader + */ + public function addExtractor($format, ExtractorInterface $extractor) + { + $this->extractors[$format] = $extractor; + } + + /** + * {@inheritdoc} + */ + public function setPrefix($prefix) + { + foreach ($this->extractors as $extractor) { + $extractor->setPrefix($prefix); + } + } + + /** + * {@inheritdoc} + */ + public function extract($directory, MessageCatalogue $catalogue) + { + foreach ($this->extractors as $extractor) { + $extractor->extract($directory, $catalogue); + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/ExtractorInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/ExtractorInterface.php new file mode 100644 index 0000000..91de201 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/ExtractorInterface.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * Extracts translation messages from a directory or files to the catalogue. + * New found messages are injected to the catalogue using the prefix. + * + * @author Michel Salib + */ +interface ExtractorInterface +{ + /** + * Extracts translation messages from files, a file or a directory to the catalogue. + * + * @param string|array $resource Files, a file or a directory + */ + public function extract($resource, MessageCatalogue $catalogue); + + /** + * Sets the prefix that should be used for new found messages. + * + * @param string $prefix The prefix + */ + public function setPrefix($prefix); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/PhpExtractor.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/PhpExtractor.php new file mode 100644 index 0000000..5237bf6 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/PhpExtractor.php @@ -0,0 +1,275 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor; + +use Symfony\Component\Finder\Finder; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * PhpExtractor extracts translation messages from a PHP template. + * + * @author Michel Salib + */ +class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface +{ + const MESSAGE_TOKEN = 300; + const METHOD_ARGUMENTS_TOKEN = 1000; + const DOMAIN_TOKEN = 1001; + + /** + * Prefix for new found message. + * + * @var string + */ + private $prefix = ''; + + /** + * The sequence that captures translation messages. + * + * @var array + */ + protected $sequences = [ + [ + '->', + 'trans', + '(', + self::MESSAGE_TOKEN, + ',', + self::METHOD_ARGUMENTS_TOKEN, + ',', + self::DOMAIN_TOKEN, + ], + [ + '->', + 'transChoice', + '(', + self::MESSAGE_TOKEN, + ',', + self::METHOD_ARGUMENTS_TOKEN, + ',', + self::METHOD_ARGUMENTS_TOKEN, + ',', + self::DOMAIN_TOKEN, + ], + [ + '->', + 'trans', + '(', + self::MESSAGE_TOKEN, + ], + [ + '->', + 'transChoice', + '(', + self::MESSAGE_TOKEN, + ], + ]; + + /** + * {@inheritdoc} + */ + public function extract($resource, MessageCatalogue $catalog) + { + $files = $this->extractFiles($resource); + foreach ($files as $file) { + $this->parseTokens(token_get_all(file_get_contents($file)), $catalog, $file); + + gc_mem_caches(); + } + } + + /** + * {@inheritdoc} + */ + public function setPrefix($prefix) + { + $this->prefix = $prefix; + } + + /** + * Normalizes a token. + * + * @param mixed $token + * + * @return string|null + */ + protected function normalizeToken($token) + { + if (isset($token[1]) && 'b"' !== $token) { + return $token[1]; + } + + return $token; + } + + /** + * Seeks to a non-whitespace token. + */ + private function seekToNextRelevantToken(\Iterator $tokenIterator) + { + for (; $tokenIterator->valid(); $tokenIterator->next()) { + $t = $tokenIterator->current(); + if (T_WHITESPACE !== $t[0]) { + break; + } + } + } + + private function skipMethodArgument(\Iterator $tokenIterator) + { + $openBraces = 0; + + for (; $tokenIterator->valid(); $tokenIterator->next()) { + $t = $tokenIterator->current(); + + if ('[' === $t[0] || '(' === $t[0]) { + ++$openBraces; + } + + if (']' === $t[0] || ')' === $t[0]) { + --$openBraces; + } + + if ((0 === $openBraces && ',' === $t[0]) || (-1 === $openBraces && ')' === $t[0])) { + break; + } + } + } + + /** + * Extracts the message from the iterator while the tokens + * match allowed message tokens. + */ + private function getValue(\Iterator $tokenIterator) + { + $message = ''; + $docToken = ''; + $docPart = ''; + + for (; $tokenIterator->valid(); $tokenIterator->next()) { + $t = $tokenIterator->current(); + if ('.' === $t) { + // Concatenate with next token + continue; + } + if (!isset($t[1])) { + break; + } + + switch ($t[0]) { + case T_START_HEREDOC: + $docToken = $t[1]; + break; + case T_ENCAPSED_AND_WHITESPACE: + case T_CONSTANT_ENCAPSED_STRING: + if ('' === $docToken) { + $message .= PhpStringTokenParser::parse($t[1]); + } else { + $docPart = $t[1]; + } + break; + case T_END_HEREDOC: + $message .= PhpStringTokenParser::parseDocString($docToken, $docPart); + $docToken = ''; + $docPart = ''; + break; + case T_WHITESPACE: + break; + default: + break 2; + } + } + + return $message; + } + + /** + * Extracts trans message from PHP tokens. + * + * @param array $tokens + * @param string $filename + */ + protected function parseTokens($tokens, MessageCatalogue $catalog/*, string $filename*/) + { + if (\func_num_args() < 3 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + @trigger_error(sprintf('The "%s()" method will have a new "string $filename" argument in version 5.0, not defining it is deprecated since Symfony 4.3.', __METHOD__), E_USER_DEPRECATED); + } + $filename = 2 < \func_num_args() ? func_get_arg(2) : ''; + + $tokenIterator = new \ArrayIterator($tokens); + + for ($key = 0; $key < $tokenIterator->count(); ++$key) { + foreach ($this->sequences as $sequence) { + $message = ''; + $domain = 'messages'; + $tokenIterator->seek($key); + + foreach ($sequence as $sequenceKey => $item) { + $this->seekToNextRelevantToken($tokenIterator); + + if ($this->normalizeToken($tokenIterator->current()) === $item) { + $tokenIterator->next(); + continue; + } elseif (self::MESSAGE_TOKEN === $item) { + $message = $this->getValue($tokenIterator); + + if (\count($sequence) === ($sequenceKey + 1)) { + break; + } + } elseif (self::METHOD_ARGUMENTS_TOKEN === $item) { + $this->skipMethodArgument($tokenIterator); + } elseif (self::DOMAIN_TOKEN === $item) { + $domainToken = $this->getValue($tokenIterator); + if ('' !== $domainToken) { + $domain = $domainToken; + } + + break; + } else { + break; + } + } + + if ($message) { + $catalog->set($message, $this->prefix.$message, $domain); + $metadata = $catalog->getMetadata($message, $domain) ?? []; + $normalizedFilename = preg_replace('{[\\\\/]+}', '/', $filename); + $metadata['sources'][] = $normalizedFilename.':'.$tokens[$key][2]; + $catalog->setMetadata($message, $metadata, $domain); + break; + } + } + } + } + + /** + * @param string $file + * + * @return bool + * + * @throws \InvalidArgumentException + */ + protected function canBeExtracted($file) + { + return $this->isFile($file) && 'php' === pathinfo($file, PATHINFO_EXTENSION); + } + + /** + * {@inheritdoc} + */ + protected function extractFromDirectory($directory) + { + $finder = new Finder(); + + return $finder->files()->name('*.php')->in($directory); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/PhpStringTokenParser.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/PhpStringTokenParser.php new file mode 100644 index 0000000..4531e91 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Extractor/PhpStringTokenParser.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor; + +/* + * The following is derived from code at http://github.com/nikic/PHP-Parser + * + * Copyright (c) 2011 by Nikita Popov + * + * Some rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * The names of the contributors may not be used to endorse or + * promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +class PhpStringTokenParser +{ + protected static $replacements = [ + '\\' => '\\', + '$' => '$', + 'n' => "\n", + 'r' => "\r", + 't' => "\t", + 'f' => "\f", + 'v' => "\v", + 'e' => "\x1B", + ]; + + /** + * Parses a string token. + * + * @param string $str String token content + * + * @return string The parsed string + */ + public static function parse($str) + { + $bLength = 0; + if ('b' === $str[0]) { + $bLength = 1; + } + + if ('\'' === $str[$bLength]) { + return str_replace( + ['\\\\', '\\\''], + ['\\', '\''], + substr($str, $bLength + 1, -1) + ); + } else { + return self::parseEscapeSequences(substr($str, $bLength + 1, -1), '"'); + } + } + + /** + * Parses escape sequences in strings (all string types apart from single quoted). + * + * @param string $str String without quotes + * @param string|null $quote Quote type + * + * @return string String with escape sequences parsed + */ + public static function parseEscapeSequences($str, $quote) + { + if (null !== $quote) { + $str = str_replace('\\'.$quote, $quote, $str); + } + + return preg_replace_callback( + '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3})~', + [__CLASS__, 'parseCallback'], + $str + ); + } + + private static function parseCallback(array $matches): string + { + $str = $matches[1]; + + if (isset(self::$replacements[$str])) { + return self::$replacements[$str]; + } elseif ('x' === $str[0] || 'X' === $str[0]) { + return \chr(hexdec($str)); + } else { + return \chr(octdec($str)); + } + } + + /** + * Parses a constant doc string. + * + * @param string $startToken Doc string start token content (<< + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Formatter; + +/** + * @author Abdellatif Ait boudad + * + * @deprecated since Symfony 4.2, use MessageFormatterInterface::format() with a %count% parameter instead + */ +interface ChoiceMessageFormatterInterface +{ + /** + * Formats a localized message pattern with given arguments. + * + * @param string $message The message (may also be an object that can be cast to string) + * @param int $number The number to use to find the indice of the message + * @param string $locale The message locale + * @param array $parameters An array of parameters for the message + * + * @return string + */ + public function choiceFormat($message, $number, $locale, array $parameters = []); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/IntlFormatter.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/IntlFormatter.php new file mode 100644 index 0000000..9101a63 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/IntlFormatter.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Formatter; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\LogicException; + +/** + * @author Guilherme Blanco + * @author Abdellatif Ait boudad + */ +class IntlFormatter implements IntlFormatterInterface +{ + private $hasMessageFormatter; + private $cache = []; + + /** + * {@inheritdoc} + */ + public function formatIntl(string $message, string $locale, array $parameters = []): string + { + // MessageFormatter constructor throws an exception if the message is empty + if ('' === $message) { + return ''; + } + + if (!$formatter = $this->cache[$locale][$message] ?? null) { + if (!($this->hasMessageFormatter ?? $this->hasMessageFormatter = class_exists(\MessageFormatter::class))) { + throw new LogicException('Cannot parse message translation: please install the "intl" PHP extension or the "symfony/polyfill-intl-messageformatter" package.'); + } + try { + $this->cache[$locale][$message] = $formatter = new \MessageFormatter($locale, $message); + } catch (\IntlException $e) { + throw new InvalidArgumentException(sprintf('Invalid message format (error #%d): '.intl_get_error_message(), intl_get_error_code()), 0, $e); + } + } + + foreach ($parameters as $key => $value) { + if (\in_array($key[0] ?? null, ['%', '{'], true)) { + unset($parameters[$key]); + $parameters[trim($key, '%{ }')] = $value; + } + } + + if (false === $message = $formatter->format($parameters)) { + throw new InvalidArgumentException(sprintf('Unable to format message (error #%s): '.$formatter->getErrorMessage(), $formatter->getErrorCode())); + } + + return $message; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/IntlFormatterInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/IntlFormatterInterface.php new file mode 100644 index 0000000..02fc6ac --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/IntlFormatterInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Formatter; + +/** + * Formats ICU message patterns. + * + * @author Nicolas Grekas + */ +interface IntlFormatterInterface +{ + /** + * Formats a localized message using rules defined by ICU MessageFormat. + * + * @see http://icu-project.org/apiref/icu4c/classMessageFormat.html#details + */ + public function formatIntl(string $message, string $locale, array $parameters = []): string; +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/MessageFormatter.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/MessageFormatter.php new file mode 100644 index 0000000..a167640 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/MessageFormatter.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Formatter; + +use Symfony\Component\Translation\IdentityTranslator; +use Symfony\Component\Translation\MessageSelector; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(IntlFormatter::class); + +/** + * @author Abdellatif Ait boudad + */ +class MessageFormatter implements MessageFormatterInterface, IntlFormatterInterface, ChoiceMessageFormatterInterface +{ + private $translator; + private $intlFormatter; + + /** + * @param TranslatorInterface|null $translator An identity translator to use as selector for pluralization + */ + public function __construct($translator = null, IntlFormatterInterface $intlFormatter = null) + { + if ($translator instanceof MessageSelector) { + $translator = new IdentityTranslator($translator); + } elseif (null !== $translator && !$translator instanceof TranslatorInterface && !$translator instanceof LegacyTranslatorInterface) { + throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be an instance of "%s", "%s" given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator))); + } + + $this->translator = $translator ?? new IdentityTranslator(); + $this->intlFormatter = $intlFormatter ?? new IntlFormatter(); + } + + /** + * {@inheritdoc} + */ + public function format($message, $locale, array $parameters = []) + { + if ($this->translator instanceof TranslatorInterface) { + return $this->translator->trans($message, $parameters, null, $locale); + } + + return strtr($message, $parameters); + } + + /** + * {@inheritdoc} + */ + public function formatIntl(string $message, string $locale, array $parameters = []): string + { + return $this->intlFormatter->formatIntl($message, $locale, $parameters); + } + + /** + * {@inheritdoc} + * + * @deprecated since Symfony 4.2, use format() with a %count% parameter instead + */ + public function choiceFormat($message, $number, $locale, array $parameters = []) + { + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the format() one instead with a %%count%% parameter.', __METHOD__), E_USER_DEPRECATED); + + $parameters = ['%count%' => $number] + $parameters; + + if ($this->translator instanceof TranslatorInterface) { + return $this->format($message, $locale, $parameters); + } + + return $this->format($this->translator->transChoice($message, $number, [], null, $locale), $locale, $parameters); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/MessageFormatterInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/MessageFormatterInterface.php new file mode 100644 index 0000000..370c055 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Formatter/MessageFormatterInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Formatter; + +/** + * @author Guilherme Blanco + * @author Abdellatif Ait boudad + */ +interface MessageFormatterInterface +{ + /** + * Formats a localized message pattern with given arguments. + * + * @param string $message The message (may also be an object that can be cast to string) + * @param string $locale The message locale + * @param array $parameters An array of parameters for the message + * + * @return string + */ + public function format($message, $locale, array $parameters = []); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/IdentityTranslator.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/IdentityTranslator.php new file mode 100644 index 0000000..87b40bf --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/IdentityTranslator.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorTrait; + +/** + * IdentityTranslator does not translate anything. + * + * @author Fabien Potencier + */ +class IdentityTranslator implements LegacyTranslatorInterface, TranslatorInterface +{ + use TranslatorTrait { + trans as private doTrans; + setLocale as private doSetLocale; + } + + private $selector; + + public function __construct(MessageSelector $selector = null) + { + $this->selector = $selector; + + if (__CLASS__ !== static::class) { + @trigger_error(sprintf('Calling "%s()" is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED); + } + } + + /** + * {@inheritdoc} + */ + public function trans($id, array $parameters = [], $domain = null, $locale = null) + { + return $this->doTrans($id, $parameters, $domain, $locale); + } + + /** + * {@inheritdoc} + */ + public function setLocale($locale) + { + $this->doSetLocale($locale); + } + + /** + * {@inheritdoc} + * + * @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter + */ + public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null) + { + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%%count%%" parameter.', __METHOD__), E_USER_DEPRECATED); + + if ($this->selector) { + return strtr($this->selector->choose((string) $id, $number, $locale ?: $this->getLocale()), $parameters); + } + + return $this->trans($id, ['%count%' => $number] + $parameters, $domain, $locale); + } + + private function getPluralizationRule(int $number, string $locale): int + { + return PluralizationRules::get($number, $locale, false); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Interval.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Interval.php new file mode 100644 index 0000000..1adc43f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Interval.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2, use IdentityTranslator instead.', Interval::class), E_USER_DEPRECATED); + +use Symfony\Component\Translation\Exception\InvalidArgumentException; + +/** + * Tests if a given number belongs to a given math interval. + * + * An interval can represent a finite set of numbers: + * + * {1,2,3,4} + * + * An interval can represent numbers between two numbers: + * + * [1, +Inf] + * ]-1,2[ + * + * The left delimiter can be [ (inclusive) or ] (exclusive). + * The right delimiter can be [ (exclusive) or ] (inclusive). + * Beside numbers, you can use -Inf and +Inf for the infinite. + * + * @author Fabien Potencier + * + * @see http://en.wikipedia.org/wiki/Interval_%28mathematics%29#The_ISO_notation + * @deprecated since Symfony 4.2, use IdentityTranslator instead + */ +class Interval +{ + /** + * Tests if the given number is in the math interval. + * + * @param int $number A number + * @param string $interval An interval + * + * @return bool + * + * @throws InvalidArgumentException + */ + public static function test($number, $interval) + { + $interval = trim($interval); + + if (!preg_match('/^'.self::getIntervalRegexp().'$/x', $interval, $matches)) { + throw new InvalidArgumentException(sprintf('"%s" is not a valid interval.', $interval)); + } + + if ($matches[1]) { + foreach (explode(',', $matches[2]) as $n) { + if ($number == $n) { + return true; + } + } + } else { + $leftNumber = self::convertNumber($matches['left']); + $rightNumber = self::convertNumber($matches['right']); + + return + ('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber) + && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber) + ; + } + + return false; + } + + /** + * Returns a Regexp that matches valid intervals. + * + * @return string A Regexp (without the delimiters) + */ + public static function getIntervalRegexp() + { + return <<[\[\]]) + \s* + (?P-Inf|\-?\d+(\.\d+)?) + \s*,\s* + (?P\+?Inf|\-?\d+(\.\d+)?) + \s* + (?P[\[\]]) +EOF; + } + + private static function convertNumber(string $number): float + { + if ('-Inf' === $number) { + return log(0); + } elseif ('+Inf' === $number || 'Inf' === $number) { + return -log(0); + } + + return (float) $number; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/LICENSE b/plugins/vdomah/jwtauth/vendor/symfony/translation/LICENSE new file mode 100644 index 0000000..9e936ec --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2020 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/ArrayLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/ArrayLoader.php new file mode 100644 index 0000000..2e9a428 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/ArrayLoader.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * ArrayLoader loads translations from a PHP array. + * + * @author Fabien Potencier + */ +class ArrayLoader implements LoaderInterface +{ + /** + * {@inheritdoc} + */ + public function load($resource, $locale, $domain = 'messages') + { + $resource = $this->flatten($resource); + $catalogue = new MessageCatalogue($locale); + $catalogue->add($resource, $domain); + + return $catalogue; + } + + /** + * Flattens an nested array of translations. + * + * The scheme used is: + * 'key' => ['key2' => ['key3' => 'value']] + * Becomes: + * 'key.key2.key3' => 'value' + */ + private function flatten(array $messages): array + { + $result = []; + foreach ($messages as $key => $value) { + if (\is_array($value)) { + foreach ($this->flatten($value) as $k => $v) { + $result[$key.'.'.$k] = $v; + } + } else { + $result[$key] = $value; + } + } + + return $result; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/CsvFileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/CsvFileLoader.php new file mode 100644 index 0000000..db17bd5 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/CsvFileLoader.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\Exception\NotFoundResourceException; + +/** + * CsvFileLoader loads translations from CSV files. + * + * @author SaÅ¡a Stamenković + */ +class CsvFileLoader extends FileLoader +{ + private $delimiter = ';'; + private $enclosure = '"'; + private $escape = '\\'; + + /** + * {@inheritdoc} + */ + protected function loadResource($resource) + { + $messages = []; + + try { + $file = new \SplFileObject($resource, 'rb'); + } catch (\RuntimeException $e) { + throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e); + } + + $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY); + $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape); + + foreach ($file as $data) { + if (false === $data) { + continue; + } + + if ('#' !== substr($data[0], 0, 1) && isset($data[1]) && 2 === \count($data)) { + $messages[$data[0]] = $data[1]; + } + } + + return $messages; + } + + /** + * Sets the delimiter, enclosure, and escape character for CSV. + * + * @param string $delimiter Delimiter character + * @param string $enclosure Enclosure character + * @param string $escape Escape character + */ + public function setCsvControl($delimiter = ';', $enclosure = '"', $escape = '\\') + { + $this->delimiter = $delimiter; + $this->enclosure = $enclosure; + $this->escape = $escape; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/FileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/FileLoader.php new file mode 100644 index 0000000..7ec54a3 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/FileLoader.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; + +/** + * @author Abdellatif Ait boudad + */ +abstract class FileLoader extends ArrayLoader +{ + /** + * {@inheritdoc} + */ + public function load($resource, $locale, $domain = 'messages') + { + if (!stream_is_local($resource)) { + throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); + } + + if (!file_exists($resource)) { + throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); + } + + $messages = $this->loadResource($resource); + + // empty resource + if (null === $messages) { + $messages = []; + } + + // not an array + if (!\is_array($messages)) { + throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource)); + } + + $catalogue = parent::load($messages, $locale, $domain); + + if (class_exists('Symfony\Component\Config\Resource\FileResource')) { + $catalogue->addResource(new FileResource($resource)); + } + + return $catalogue; + } + + /** + * @param string $resource + * + * @return array + * + * @throws InvalidResourceException if stream content has an invalid format + */ + abstract protected function loadResource($resource); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/IcuDatFileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/IcuDatFileLoader.php new file mode 100644 index 0000000..545c2b0 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/IcuDatFileLoader.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * IcuResFileLoader loads translations from a resource bundle. + * + * @author stealth35 + */ +class IcuDatFileLoader extends IcuResFileLoader +{ + /** + * {@inheritdoc} + */ + public function load($resource, $locale, $domain = 'messages') + { + if (!stream_is_local($resource.'.dat')) { + throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); + } + + if (!file_exists($resource.'.dat')) { + throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); + } + + try { + $rb = new \ResourceBundle($locale, $resource); + } catch (\Exception $e) { + $rb = null; + } + + if (!$rb) { + throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource)); + } elseif (intl_is_failure($rb->getErrorCode())) { + throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode()); + } + + $messages = $this->flatten($rb); + $catalogue = new MessageCatalogue($locale); + $catalogue->add($messages, $domain); + + if (class_exists('Symfony\Component\Config\Resource\FileResource')) { + $catalogue->addResource(new FileResource($resource.'.dat')); + } + + return $catalogue; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/IcuResFileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/IcuResFileLoader.php new file mode 100644 index 0000000..6dddf63 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/IcuResFileLoader.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Config\Resource\DirectoryResource; +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * IcuResFileLoader loads translations from a resource bundle. + * + * @author stealth35 + */ +class IcuResFileLoader implements LoaderInterface +{ + /** + * {@inheritdoc} + */ + public function load($resource, $locale, $domain = 'messages') + { + if (!stream_is_local($resource)) { + throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); + } + + if (!is_dir($resource)) { + throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); + } + + try { + $rb = new \ResourceBundle($locale, $resource); + } catch (\Exception $e) { + $rb = null; + } + + if (!$rb) { + throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource)); + } elseif (intl_is_failure($rb->getErrorCode())) { + throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode()); + } + + $messages = $this->flatten($rb); + $catalogue = new MessageCatalogue($locale); + $catalogue->add($messages, $domain); + + if (class_exists('Symfony\Component\Config\Resource\DirectoryResource')) { + $catalogue->addResource(new DirectoryResource($resource)); + } + + return $catalogue; + } + + /** + * Flattens an ResourceBundle. + * + * The scheme used is: + * key { key2 { key3 { "value" } } } + * Becomes: + * 'key.key2.key3' => 'value' + * + * This function takes an array by reference and will modify it + * + * @param \ResourceBundle $rb The ResourceBundle that will be flattened + * @param array $messages Used internally for recursive calls + * @param string $path Current path being parsed, used internally for recursive calls + * + * @return array the flattened ResourceBundle + */ + protected function flatten(\ResourceBundle $rb, array &$messages = [], $path = null) + { + foreach ($rb as $key => $value) { + $nodePath = $path ? $path.'.'.$key : $key; + if ($value instanceof \ResourceBundle) { + $this->flatten($value, $messages, $nodePath); + } else { + $messages[$nodePath] = $value; + } + } + + return $messages; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/IniFileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/IniFileLoader.php new file mode 100644 index 0000000..11d9b27 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/IniFileLoader.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +/** + * IniFileLoader loads translations from an ini file. + * + * @author stealth35 + */ +class IniFileLoader extends FileLoader +{ + /** + * {@inheritdoc} + */ + protected function loadResource($resource) + { + return parse_ini_file($resource, true); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/JsonFileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/JsonFileLoader.php new file mode 100644 index 0000000..9f15dbc --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/JsonFileLoader.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\Exception\InvalidResourceException; + +/** + * JsonFileLoader loads translations from an json file. + * + * @author singles + */ +class JsonFileLoader extends FileLoader +{ + /** + * {@inheritdoc} + */ + protected function loadResource($resource) + { + $messages = []; + if ($data = file_get_contents($resource)) { + $messages = json_decode($data, true); + + if (0 < $errorCode = json_last_error()) { + throw new InvalidResourceException('Error parsing JSON: '.$this->getJSONErrorMessage($errorCode)); + } + } + + return $messages; + } + + /** + * Translates JSON_ERROR_* constant into meaningful message. + */ + private function getJSONErrorMessage(int $errorCode): string + { + switch ($errorCode) { + case JSON_ERROR_DEPTH: + return 'Maximum stack depth exceeded'; + case JSON_ERROR_STATE_MISMATCH: + return 'Underflow or the modes mismatch'; + case JSON_ERROR_CTRL_CHAR: + return 'Unexpected control character found'; + case JSON_ERROR_SYNTAX: + return 'Syntax error, malformed JSON'; + case JSON_ERROR_UTF8: + return 'Malformed UTF-8 characters, possibly incorrectly encoded'; + default: + return 'Unknown error'; + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/LoaderInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/LoaderInterface.php new file mode 100644 index 0000000..1785402 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/LoaderInterface.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * LoaderInterface is the interface implemented by all translation loaders. + * + * @author Fabien Potencier + */ +interface LoaderInterface +{ + /** + * Loads a locale. + * + * @param mixed $resource A resource + * @param string $locale A locale + * @param string $domain The domain + * + * @return MessageCatalogue A MessageCatalogue instance + * + * @throws NotFoundResourceException when the resource cannot be found + * @throws InvalidResourceException when the resource cannot be loaded + */ + public function load($resource, $locale, $domain = 'messages'); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/MoFileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/MoFileLoader.php new file mode 100644 index 0000000..d344c6e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/MoFileLoader.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\Exception\InvalidResourceException; + +/** + * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/) + */ +class MoFileLoader extends FileLoader +{ + /** + * Magic used for validating the format of a MO file as well as + * detecting if the machine used to create that file was little endian. + */ + const MO_LITTLE_ENDIAN_MAGIC = 0x950412de; + + /** + * Magic used for validating the format of a MO file as well as + * detecting if the machine used to create that file was big endian. + */ + const MO_BIG_ENDIAN_MAGIC = 0xde120495; + + /** + * The size of the header of a MO file in bytes. + */ + const MO_HEADER_SIZE = 28; + + /** + * Parses machine object (MO) format, independent of the machine's endian it + * was created on. Both 32bit and 64bit systems are supported. + * + * {@inheritdoc} + */ + protected function loadResource($resource) + { + $stream = fopen($resource, 'r'); + + $stat = fstat($stream); + + if ($stat['size'] < self::MO_HEADER_SIZE) { + throw new InvalidResourceException('MO stream content has an invalid format.'); + } + $magic = unpack('V1', fread($stream, 4)); + $magic = hexdec(substr(dechex(current($magic)), -8)); + + if (self::MO_LITTLE_ENDIAN_MAGIC == $magic) { + $isBigEndian = false; + } elseif (self::MO_BIG_ENDIAN_MAGIC == $magic) { + $isBigEndian = true; + } else { + throw new InvalidResourceException('MO stream content has an invalid format.'); + } + + // formatRevision + $this->readLong($stream, $isBigEndian); + $count = $this->readLong($stream, $isBigEndian); + $offsetId = $this->readLong($stream, $isBigEndian); + $offsetTranslated = $this->readLong($stream, $isBigEndian); + // sizeHashes + $this->readLong($stream, $isBigEndian); + // offsetHashes + $this->readLong($stream, $isBigEndian); + + $messages = []; + + for ($i = 0; $i < $count; ++$i) { + $pluralId = null; + $translated = null; + + fseek($stream, $offsetId + $i * 8); + + $length = $this->readLong($stream, $isBigEndian); + $offset = $this->readLong($stream, $isBigEndian); + + if ($length < 1) { + continue; + } + + fseek($stream, $offset); + $singularId = fread($stream, $length); + + if (false !== strpos($singularId, "\000")) { + list($singularId, $pluralId) = explode("\000", $singularId); + } + + fseek($stream, $offsetTranslated + $i * 8); + $length = $this->readLong($stream, $isBigEndian); + $offset = $this->readLong($stream, $isBigEndian); + + if ($length < 1) { + continue; + } + + fseek($stream, $offset); + $translated = fread($stream, $length); + + if (false !== strpos($translated, "\000")) { + $translated = explode("\000", $translated); + } + + $ids = ['singular' => $singularId, 'plural' => $pluralId]; + $item = compact('ids', 'translated'); + + if (!empty($item['ids']['singular'])) { + $id = $item['ids']['singular']; + if (isset($item['ids']['plural'])) { + $id .= '|'.$item['ids']['plural']; + } + $messages[$id] = stripcslashes(implode('|', (array) $item['translated'])); + } + } + + fclose($stream); + + return array_filter($messages); + } + + /** + * Reads an unsigned long from stream respecting endianness. + * + * @param resource $stream + */ + private function readLong($stream, bool $isBigEndian): int + { + $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4)); + $result = current($result); + + return (int) substr($result, -8); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/PhpFileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/PhpFileLoader.php new file mode 100644 index 0000000..0991c3d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/PhpFileLoader.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +/** + * PhpFileLoader loads translations from PHP files returning an array of translations. + * + * @author Fabien Potencier + */ +class PhpFileLoader extends FileLoader +{ + private static $cache = []; + + /** + * {@inheritdoc} + */ + protected function loadResource($resource) + { + if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), FILTER_VALIDATE_BOOLEAN))) { + self::$cache = null; + } + + if (null === self::$cache) { + return require $resource; + } + + if (isset(self::$cache[$resource])) { + return self::$cache[$resource]; + } + + return self::$cache[$resource] = require $resource; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/PoFileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/PoFileLoader.php new file mode 100644 index 0000000..5e460fb --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/PoFileLoader.php @@ -0,0 +1,149 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +/** + * @copyright Copyright (c) 2010, Union of RAD https://github.com/UnionOfRAD/lithium + * @copyright Copyright (c) 2012, Clemens Tolboom + */ +class PoFileLoader extends FileLoader +{ + /** + * Parses portable object (PO) format. + * + * From https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files + * we should be able to parse files having: + * + * white-space + * # translator-comments + * #. extracted-comments + * #: reference... + * #, flag... + * #| msgid previous-untranslated-string + * msgid untranslated-string + * msgstr translated-string + * + * extra or different lines are: + * + * #| msgctxt previous-context + * #| msgid previous-untranslated-string + * msgctxt context + * + * #| msgid previous-untranslated-string-singular + * #| msgid_plural previous-untranslated-string-plural + * msgid untranslated-string-singular + * msgid_plural untranslated-string-plural + * msgstr[0] translated-string-case-0 + * ... + * msgstr[N] translated-string-case-n + * + * The definition states: + * - white-space and comments are optional. + * - msgid "" that an empty singleline defines a header. + * + * This parser sacrifices some features of the reference implementation the + * differences to that implementation are as follows. + * - No support for comments spanning multiple lines. + * - Translator and extracted comments are treated as being the same type. + * - Message IDs are allowed to have other encodings as just US-ASCII. + * + * Items with an empty id are ignored. + * + * {@inheritdoc} + */ + protected function loadResource($resource) + { + $stream = fopen($resource, 'r'); + + $defaults = [ + 'ids' => [], + 'translated' => null, + ]; + + $messages = []; + $item = $defaults; + $flags = []; + + while ($line = fgets($stream)) { + $line = trim($line); + + if ('' === $line) { + // Whitespace indicated current item is done + if (!\in_array('fuzzy', $flags)) { + $this->addMessage($messages, $item); + } + $item = $defaults; + $flags = []; + } elseif ('#,' === substr($line, 0, 2)) { + $flags = array_map('trim', explode(',', substr($line, 2))); + } elseif ('msgid "' === substr($line, 0, 7)) { + // We start a new msg so save previous + // TODO: this fails when comments or contexts are added + $this->addMessage($messages, $item); + $item = $defaults; + $item['ids']['singular'] = substr($line, 7, -1); + } elseif ('msgstr "' === substr($line, 0, 8)) { + $item['translated'] = substr($line, 8, -1); + } elseif ('"' === $line[0]) { + $continues = isset($item['translated']) ? 'translated' : 'ids'; + + if (\is_array($item[$continues])) { + end($item[$continues]); + $item[$continues][key($item[$continues])] .= substr($line, 1, -1); + } else { + $item[$continues] .= substr($line, 1, -1); + } + } elseif ('msgid_plural "' === substr($line, 0, 14)) { + $item['ids']['plural'] = substr($line, 14, -1); + } elseif ('msgstr[' === substr($line, 0, 7)) { + $size = strpos($line, ']'); + $item['translated'][(int) substr($line, 7, 1)] = substr($line, $size + 3, -1); + } + } + // save last item + if (!\in_array('fuzzy', $flags)) { + $this->addMessage($messages, $item); + } + fclose($stream); + + return $messages; + } + + /** + * Save a translation item to the messages. + * + * A .po file could contain by error missing plural indexes. We need to + * fix these before saving them. + */ + private function addMessage(array &$messages, array $item) + { + if (!empty($item['ids']['singular'])) { + $id = stripcslashes($item['ids']['singular']); + if (isset($item['ids']['plural'])) { + $id .= '|'.stripcslashes($item['ids']['plural']); + } + + $translated = (array) $item['translated']; + // PO are by definition indexed so sort by index. + ksort($translated); + // Make sure every index is filled. + end($translated); + $count = key($translated); + // Fill missing spots with '-'. + $empties = array_fill(0, $count + 1, '-'); + $translated += $empties; + ksort($translated); + + $messages[$id] = stripcslashes(implode('|', $translated)); + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/QtFileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/QtFileLoader.php new file mode 100644 index 0000000..2d4a4c0 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/QtFileLoader.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Config\Util\XmlUtils; +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * QtFileLoader loads translations from QT Translations XML files. + * + * @author Benjamin Eberlei + */ +class QtFileLoader implements LoaderInterface +{ + /** + * {@inheritdoc} + */ + public function load($resource, $locale, $domain = 'messages') + { + if (!stream_is_local($resource)) { + throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); + } + + if (!file_exists($resource)) { + throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); + } + + try { + $dom = XmlUtils::loadFile($resource); + } catch (\InvalidArgumentException $e) { + throw new InvalidResourceException(sprintf('Unable to load "%s".', $resource), $e->getCode(), $e); + } + + $internalErrors = libxml_use_internal_errors(true); + libxml_clear_errors(); + + $xpath = new \DOMXPath($dom); + $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]'); + + $catalogue = new MessageCatalogue($locale); + if (1 == $nodes->length) { + $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message'); + foreach ($translations as $translation) { + $translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue; + + if (!empty($translationValue)) { + $catalogue->set( + (string) $translation->getElementsByTagName('source')->item(0)->nodeValue, + $translationValue, + $domain + ); + } + $translation = $translation->nextSibling; + } + + if (class_exists('Symfony\Component\Config\Resource\FileResource')) { + $catalogue->addResource(new FileResource($resource)); + } + } + + libxml_use_internal_errors($internalErrors); + + return $catalogue; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/XliffFileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/XliffFileLoader.php new file mode 100644 index 0000000..f9056d9 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/XliffFileLoader.php @@ -0,0 +1,208 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Config\Util\XmlUtils; +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Util\XliffUtils; + +/** + * XliffFileLoader loads translations from XLIFF files. + * + * @author Fabien Potencier + */ +class XliffFileLoader implements LoaderInterface +{ + /** + * {@inheritdoc} + */ + public function load($resource, $locale, $domain = 'messages') + { + if (!stream_is_local($resource)) { + throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); + } + + if (!file_exists($resource)) { + throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); + } + + $catalogue = new MessageCatalogue($locale); + $this->extract($resource, $catalogue, $domain); + + if (class_exists('Symfony\Component\Config\Resource\FileResource')) { + $catalogue->addResource(new FileResource($resource)); + } + + return $catalogue; + } + + private function extract($resource, MessageCatalogue $catalogue, string $domain) + { + try { + $dom = XmlUtils::loadFile($resource); + } catch (\InvalidArgumentException $e) { + throw new InvalidResourceException(sprintf('Unable to load "%s": ', $resource).$e->getMessage(), $e->getCode(), $e); + } + + $xliffVersion = XliffUtils::getVersionNumber($dom); + if ($errors = XliffUtils::validateSchema($dom)) { + throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: '.XliffUtils::getErrorsAsString($errors), $resource)); + } + + if ('1.2' === $xliffVersion) { + $this->extractXliff1($dom, $catalogue, $domain); + } + + if ('2.0' === $xliffVersion) { + $this->extractXliff2($dom, $catalogue, $domain); + } + } + + /** + * Extract messages and metadata from DOMDocument into a MessageCatalogue. + */ + private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain) + { + $xml = simplexml_import_dom($dom); + $encoding = strtoupper($dom->encoding); + + $namespace = 'urn:oasis:names:tc:xliff:document:1.2'; + $xml->registerXPathNamespace('xliff', $namespace); + + foreach ($xml->xpath('//xliff:file') as $file) { + $fileAttributes = $file->attributes(); + + $file->registerXPathNamespace('xliff', $namespace); + + foreach ($file->xpath('.//xliff:trans-unit') as $translation) { + $attributes = $translation->attributes(); + + if (!(isset($attributes['resname']) || isset($translation->source))) { + continue; + } + + $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source; + // If the xlf file has another encoding specified, try to convert it because + // simple_xml will always return utf-8 encoded values + $target = $this->utf8ToCharset((string) ($translation->target ?? $translation->source), $encoding); + + $catalogue->set((string) $source, $target, $domain); + + $metadata = [ + 'source' => (string) $translation->source, + 'file' => [ + 'original' => (string) $fileAttributes['original'], + ], + ]; + if ($notes = $this->parseNotesMetadata($translation->note, $encoding)) { + $metadata['notes'] = $notes; + } + + if (isset($translation->target) && $translation->target->attributes()) { + $metadata['target-attributes'] = []; + foreach ($translation->target->attributes() as $key => $value) { + $metadata['target-attributes'][$key] = (string) $value; + } + } + + if (isset($attributes['id'])) { + $metadata['id'] = (string) $attributes['id']; + } + + $catalogue->setMetadata((string) $source, $metadata, $domain); + } + } + } + + private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain) + { + $xml = simplexml_import_dom($dom); + $encoding = strtoupper($dom->encoding); + + $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:2.0'); + + foreach ($xml->xpath('//xliff:unit') as $unit) { + foreach ($unit->segment as $segment) { + $source = $segment->source; + + // If the xlf file has another encoding specified, try to convert it because + // simple_xml will always return utf-8 encoded values + $target = $this->utf8ToCharset((string) (isset($segment->target) ? $segment->target : $source), $encoding); + + $catalogue->set((string) $source, $target, $domain); + + $metadata = []; + if (isset($segment->target) && $segment->target->attributes()) { + $metadata['target-attributes'] = []; + foreach ($segment->target->attributes() as $key => $value) { + $metadata['target-attributes'][$key] = (string) $value; + } + } + + if (isset($unit->notes)) { + $metadata['notes'] = []; + foreach ($unit->notes->note as $noteNode) { + $note = []; + foreach ($noteNode->attributes() as $key => $value) { + $note[$key] = (string) $value; + } + $note['content'] = (string) $noteNode; + $metadata['notes'][] = $note; + } + } + + $catalogue->setMetadata((string) $source, $metadata, $domain); + } + } + } + + /** + * Convert a UTF8 string to the specified encoding. + */ + private function utf8ToCharset(string $content, string $encoding = null): string + { + if ('UTF-8' !== $encoding && !empty($encoding)) { + return mb_convert_encoding($content, $encoding, 'UTF-8'); + } + + return $content; + } + + private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, string $encoding = null): array + { + $notes = []; + + if (null === $noteElement) { + return $notes; + } + + /** @var \SimpleXMLElement $xmlNote */ + foreach ($noteElement as $xmlNote) { + $noteAttributes = $xmlNote->attributes(); + $note = ['content' => $this->utf8ToCharset((string) $xmlNote, $encoding)]; + if (isset($noteAttributes['priority'])) { + $note['priority'] = (int) $noteAttributes['priority']; + } + + if (isset($noteAttributes['from'])) { + $note['from'] = (string) $noteAttributes['from']; + } + + $notes[] = $note; + } + + return $notes; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/YamlFileLoader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/YamlFileLoader.php new file mode 100644 index 0000000..e4bee0c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Loader/YamlFileLoader.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\LogicException; +use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Parser as YamlParser; +use Symfony\Component\Yaml\Yaml; + +/** + * YamlFileLoader loads translations from Yaml files. + * + * @author Fabien Potencier + */ +class YamlFileLoader extends FileLoader +{ + private $yamlParser; + + /** + * {@inheritdoc} + */ + protected function loadResource($resource) + { + if (null === $this->yamlParser) { + if (!class_exists('Symfony\Component\Yaml\Parser')) { + throw new LogicException('Loading translations from the YAML format requires the Symfony Yaml component.'); + } + + $this->yamlParser = new YamlParser(); + } + + try { + $messages = $this->yamlParser->parseFile($resource, Yaml::PARSE_CONSTANT); + } catch (ParseException $e) { + throw new InvalidResourceException(sprintf('The file "%s" does not contain valid YAML: ', $resource).$e->getMessage(), 0, $e); + } + + if (null !== $messages && !\is_array($messages)) { + throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource)); + } + + return $messages ?: []; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/LoggingTranslator.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/LoggingTranslator.php new file mode 100644 index 0000000..a001192 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/LoggingTranslator.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * @author Abdellatif Ait boudad + */ +class LoggingTranslator implements TranslatorInterface, LegacyTranslatorInterface, TranslatorBagInterface +{ + /** + * @var TranslatorInterface|TranslatorBagInterface + */ + private $translator; + + private $logger; + + /** + * @param TranslatorInterface $translator The translator must implement TranslatorBagInterface + */ + public function __construct($translator, LoggerInterface $logger) + { + if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) { + throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be an instance of "%s", "%s" given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator))); + } + if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) { + throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', \get_class($translator))); + } + + $this->translator = $translator; + $this->logger = $logger; + } + + /** + * {@inheritdoc} + */ + public function trans($id, array $parameters = [], $domain = null, $locale = null) + { + $trans = $this->translator->trans($id, $parameters, $domain, $locale); + $this->log($id, $domain, $locale); + + return $trans; + } + + /** + * {@inheritdoc} + * + * @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter + */ + public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null) + { + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%%count%%" parameter.', __METHOD__), E_USER_DEPRECATED); + + if ($this->translator instanceof TranslatorInterface) { + $trans = $this->translator->trans($id, ['%count%' => $number] + $parameters, $domain, $locale); + } else { + $trans = $this->translator->transChoice($id, $number, $parameters, $domain, $locale); + } + + $this->log($id, $domain, $locale); + + return $trans; + } + + /** + * {@inheritdoc} + */ + public function setLocale($locale) + { + $prev = $this->translator->getLocale(); + $this->translator->setLocale($locale); + if ($prev === $locale) { + return; + } + + $this->logger->debug(sprintf('The locale of the translator has changed from "%s" to "%s".', $prev, $locale)); + } + + /** + * {@inheritdoc} + */ + public function getLocale() + { + return $this->translator->getLocale(); + } + + /** + * {@inheritdoc} + */ + public function getCatalogue($locale = null) + { + return $this->translator->getCatalogue($locale); + } + + /** + * Gets the fallback locales. + * + * @return array The fallback locales + */ + public function getFallbackLocales() + { + if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) { + return $this->translator->getFallbackLocales(); + } + + return []; + } + + /** + * Passes through all unknown calls onto the translator object. + */ + public function __call($method, $args) + { + return $this->translator->{$method}(...$args); + } + + /** + * Logs for missing translations. + */ + private function log(?string $id, ?string $domain, ?string $locale) + { + if (null === $domain) { + $domain = 'messages'; + } + + $id = (string) $id; + $catalogue = $this->translator->getCatalogue($locale); + if ($catalogue->defines($id, $domain)) { + return; + } + + if ($catalogue->has($id, $domain)) { + $this->logger->debug('Translation use fallback catalogue.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]); + } else { + $this->logger->warning('Translation not found.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]); + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/MessageCatalogue.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/MessageCatalogue.php new file mode 100644 index 0000000..75ec5b4 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/MessageCatalogue.php @@ -0,0 +1,322 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\Config\Resource\ResourceInterface; +use Symfony\Component\Translation\Exception\LogicException; + +/** + * @author Fabien Potencier + */ +class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface +{ + private $messages = []; + private $metadata = []; + private $resources = []; + private $locale; + private $fallbackCatalogue; + private $parent; + + /** + * @param string $locale The locale + * @param array $messages An array of messages classified by domain + */ + public function __construct(?string $locale, array $messages = []) + { + if (null === $locale) { + @trigger_error(sprintf('Passing "null" to the first argument of the "%s" method has been deprecated since Symfony 4.4 and will throw an error in 5.0.', __METHOD__), E_USER_DEPRECATED); + } + + $this->locale = $locale; + $this->messages = $messages; + } + + /** + * {@inheritdoc} + */ + public function getLocale() + { + return $this->locale; + } + + /** + * {@inheritdoc} + */ + public function getDomains() + { + $domains = []; + $suffixLength = \strlen(self::INTL_DOMAIN_SUFFIX); + + foreach ($this->messages as $domain => $messages) { + if (\strlen($domain) > $suffixLength && false !== $i = strpos($domain, self::INTL_DOMAIN_SUFFIX, -$suffixLength)) { + $domain = substr($domain, 0, $i); + } + $domains[$domain] = $domain; + } + + return array_values($domains); + } + + /** + * {@inheritdoc} + */ + public function all($domain = null) + { + if (null !== $domain) { + // skip messages merge if intl-icu requested explicitly + if (false !== strpos($domain, self::INTL_DOMAIN_SUFFIX)) { + return $this->messages[$domain] ?? []; + } + + return ($this->messages[$domain.self::INTL_DOMAIN_SUFFIX] ?? []) + ($this->messages[$domain] ?? []); + } + + $allMessages = []; + $suffixLength = \strlen(self::INTL_DOMAIN_SUFFIX); + + foreach ($this->messages as $domain => $messages) { + if (\strlen($domain) > $suffixLength && false !== $i = strpos($domain, self::INTL_DOMAIN_SUFFIX, -$suffixLength)) { + $domain = substr($domain, 0, $i); + $allMessages[$domain] = $messages + ($allMessages[$domain] ?? []); + } else { + $allMessages[$domain] = ($allMessages[$domain] ?? []) + $messages; + } + } + + return $allMessages; + } + + /** + * {@inheritdoc} + */ + public function set($id, $translation, $domain = 'messages') + { + $this->add([$id => $translation], $domain); + } + + /** + * {@inheritdoc} + */ + public function has($id, $domain = 'messages') + { + if (isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) { + return true; + } + + if (null !== $this->fallbackCatalogue) { + return $this->fallbackCatalogue->has($id, $domain); + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function defines($id, $domain = 'messages') + { + return isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id]); + } + + /** + * {@inheritdoc} + */ + public function get($id, $domain = 'messages') + { + if (isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) { + return $this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id]; + } + + if (isset($this->messages[$domain][$id])) { + return $this->messages[$domain][$id]; + } + + if (null !== $this->fallbackCatalogue) { + return $this->fallbackCatalogue->get($id, $domain); + } + + return $id; + } + + /** + * {@inheritdoc} + */ + public function replace($messages, $domain = 'messages') + { + unset($this->messages[$domain], $this->messages[$domain.self::INTL_DOMAIN_SUFFIX]); + + $this->add($messages, $domain); + } + + /** + * {@inheritdoc} + */ + public function add($messages, $domain = 'messages') + { + if (!isset($this->messages[$domain])) { + $this->messages[$domain] = []; + } + $intlDomain = $domain; + $suffixLength = \strlen(self::INTL_DOMAIN_SUFFIX); + if (\strlen($domain) > $suffixLength && false !== strpos($domain, self::INTL_DOMAIN_SUFFIX, -$suffixLength)) { + $intlDomain .= self::INTL_DOMAIN_SUFFIX; + } + foreach ($messages as $id => $message) { + if (isset($this->messages[$intlDomain]) && \array_key_exists($id, $this->messages[$intlDomain])) { + $this->messages[$intlDomain][$id] = $message; + } else { + $this->messages[$domain][$id] = $message; + } + } + } + + /** + * {@inheritdoc} + */ + public function addCatalogue(MessageCatalogueInterface $catalogue) + { + if ($catalogue->getLocale() !== $this->locale) { + throw new LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s".', $catalogue->getLocale(), $this->locale)); + } + + foreach ($catalogue->all() as $domain => $messages) { + if ($intlMessages = $catalogue->all($domain.self::INTL_DOMAIN_SUFFIX)) { + $this->add($intlMessages, $domain.self::INTL_DOMAIN_SUFFIX); + $messages = array_diff_key($messages, $intlMessages); + } + $this->add($messages, $domain); + } + + foreach ($catalogue->getResources() as $resource) { + $this->addResource($resource); + } + + if ($catalogue instanceof MetadataAwareInterface) { + $metadata = $catalogue->getMetadata('', ''); + $this->addMetadata($metadata); + } + } + + /** + * {@inheritdoc} + */ + public function addFallbackCatalogue(MessageCatalogueInterface $catalogue) + { + // detect circular references + $c = $catalogue; + while ($c = $c->getFallbackCatalogue()) { + if ($c->getLocale() === $this->getLocale()) { + throw new LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale())); + } + } + + $c = $this; + do { + if ($c->getLocale() === $catalogue->getLocale()) { + throw new LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale())); + } + + foreach ($catalogue->getResources() as $resource) { + $c->addResource($resource); + } + } while ($c = $c->parent); + + $catalogue->parent = $this; + $this->fallbackCatalogue = $catalogue; + + foreach ($catalogue->getResources() as $resource) { + $this->addResource($resource); + } + } + + /** + * {@inheritdoc} + */ + public function getFallbackCatalogue() + { + return $this->fallbackCatalogue; + } + + /** + * {@inheritdoc} + */ + public function getResources() + { + return array_values($this->resources); + } + + /** + * {@inheritdoc} + */ + public function addResource(ResourceInterface $resource) + { + $this->resources[$resource->__toString()] = $resource; + } + + /** + * {@inheritdoc} + */ + public function getMetadata($key = '', $domain = 'messages') + { + if ('' == $domain) { + return $this->metadata; + } + + if (isset($this->metadata[$domain])) { + if ('' == $key) { + return $this->metadata[$domain]; + } + + if (isset($this->metadata[$domain][$key])) { + return $this->metadata[$domain][$key]; + } + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function setMetadata($key, $value, $domain = 'messages') + { + $this->metadata[$domain][$key] = $value; + } + + /** + * {@inheritdoc} + */ + public function deleteMetadata($key = '', $domain = 'messages') + { + if ('' == $domain) { + $this->metadata = []; + } elseif ('' == $key) { + unset($this->metadata[$domain]); + } else { + unset($this->metadata[$domain][$key]); + } + } + + /** + * Adds current values with the new values. + * + * @param array $values Values to add + */ + private function addMetadata(array $values) + { + foreach ($values as $domain => $keys) { + foreach ($keys as $key => $value) { + $this->setMetadata($key, $value, $domain); + } + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/MessageCatalogueInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/MessageCatalogueInterface.php new file mode 100644 index 0000000..f3d3f5e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/MessageCatalogueInterface.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\Config\Resource\ResourceInterface; + +/** + * MessageCatalogueInterface. + * + * @author Fabien Potencier + */ +interface MessageCatalogueInterface +{ + const INTL_DOMAIN_SUFFIX = '+intl-icu'; + + /** + * Gets the catalogue locale. + * + * @return string The locale + */ + public function getLocale(); + + /** + * Gets the domains. + * + * @return array An array of domains + */ + public function getDomains(); + + /** + * Gets the messages within a given domain. + * + * If $domain is null, it returns all messages. + * + * @param string $domain The domain name + * + * @return array An array of messages + */ + public function all($domain = null); + + /** + * Sets a message translation. + * + * @param string $id The message id + * @param string $translation The messages translation + * @param string $domain The domain name + */ + public function set($id, $translation, $domain = 'messages'); + + /** + * Checks if a message has a translation. + * + * @param string $id The message id + * @param string $domain The domain name + * + * @return bool true if the message has a translation, false otherwise + */ + public function has($id, $domain = 'messages'); + + /** + * Checks if a message has a translation (it does not take into account the fallback mechanism). + * + * @param string $id The message id + * @param string $domain The domain name + * + * @return bool true if the message has a translation, false otherwise + */ + public function defines($id, $domain = 'messages'); + + /** + * Gets a message translation. + * + * @param string $id The message id + * @param string $domain The domain name + * + * @return string The message translation + */ + public function get($id, $domain = 'messages'); + + /** + * Sets translations for a given domain. + * + * @param array $messages An array of translations + * @param string $domain The domain name + */ + public function replace($messages, $domain = 'messages'); + + /** + * Adds translations for a given domain. + * + * @param array $messages An array of translations + * @param string $domain The domain name + */ + public function add($messages, $domain = 'messages'); + + /** + * Merges translations from the given Catalogue into the current one. + * + * The two catalogues must have the same locale. + */ + public function addCatalogue(self $catalogue); + + /** + * Merges translations from the given Catalogue into the current one + * only when the translation does not exist. + * + * This is used to provide default translations when they do not exist for the current locale. + */ + public function addFallbackCatalogue(self $catalogue); + + /** + * Gets the fallback catalogue. + * + * @return self|null A MessageCatalogueInterface instance or null when no fallback has been set + */ + public function getFallbackCatalogue(); + + /** + * Returns an array of resources loaded to build this collection. + * + * @return ResourceInterface[] An array of resources + */ + public function getResources(); + + /** + * Adds a resource for this collection. + */ + public function addResource(ResourceInterface $resource); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/MessageSelector.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/MessageSelector.php new file mode 100644 index 0000000..0f0febb --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/MessageSelector.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2, use IdentityTranslator instead.', MessageSelector::class), E_USER_DEPRECATED); + +use Symfony\Component\Translation\Exception\InvalidArgumentException; + +/** + * MessageSelector. + * + * @author Fabien Potencier + * @author Bernhard Schussek + * + * @deprecated since Symfony 4.2, use IdentityTranslator instead. + */ +class MessageSelector +{ + /** + * Given a message with different plural translations separated by a + * pipe (|), this method returns the correct portion of the message based + * on the given number, locale and the pluralization rules in the message + * itself. + * + * The message supports two different types of pluralization rules: + * + * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples + * indexed: There is one apple|There are %count% apples + * + * The indexed solution can also contain labels (e.g. one: There is one apple). + * This is purely for making the translations more clear - it does not + * affect the functionality. + * + * The two methods can also be mixed: + * {0} There are no apples|one: There is one apple|more: There are %count% apples + * + * @param string $message The message being translated + * @param int|float $number The number of items represented for the message + * @param string $locale The locale to use for choosing + * + * @return string + * + * @throws InvalidArgumentException + */ + public function choose($message, $number, $locale) + { + $parts = []; + if (preg_match('/^\|++$/', $message)) { + $parts = explode('|', $message); + } elseif (preg_match_all('/(?:\|\||[^\|])++/', $message, $matches)) { + $parts = $matches[0]; + } + + $explicitRules = []; + $standardRules = []; + foreach ($parts as $part) { + $part = trim(str_replace('||', '|', $part)); + + if (preg_match('/^(?P'.Interval::getIntervalRegexp().')\s*(?P.*?)$/xs', $part, $matches)) { + $explicitRules[$matches['interval']] = $matches['message']; + } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) { + $standardRules[] = $matches[1]; + } else { + $standardRules[] = $part; + } + } + + // try to match an explicit rule, then fallback to the standard ones + foreach ($explicitRules as $interval => $m) { + if (Interval::test($number, $interval)) { + return $m; + } + } + + $position = PluralizationRules::get($number, $locale); + + if (!isset($standardRules[$position])) { + // when there's exactly one rule given, and that rule is a standard + // rule, use this rule + if (1 === \count($parts) && isset($standardRules[0])) { + return $standardRules[0]; + } + + throw new InvalidArgumentException(sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $message, $locale, $number)); + } + + return $standardRules[$position]; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/MetadataAwareInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/MetadataAwareInterface.php new file mode 100644 index 0000000..e93c6fb --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/MetadataAwareInterface.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +/** + * MetadataAwareInterface. + * + * @author Fabien Potencier + */ +interface MetadataAwareInterface +{ + /** + * Gets metadata for the given domain and key. + * + * Passing an empty domain will return an array with all metadata indexed by + * domain and then by key. Passing an empty key will return an array with all + * metadata for the given domain. + * + * @param string $key The key + * @param string $domain The domain name + * + * @return mixed The value that was set or an array with the domains/keys or null + */ + public function getMetadata($key = '', $domain = 'messages'); + + /** + * Adds metadata to a message domain. + * + * @param string $key The key + * @param mixed $value The value + * @param string $domain The domain name + */ + public function setMetadata($key, $value, $domain = 'messages'); + + /** + * Deletes metadata for the given key and domain. + * + * Passing an empty domain will delete all metadata. Passing an empty key will + * delete all metadata for the given domain. + * + * @param string $key The key + * @param string $domain The domain name + */ + public function deleteMetadata($key = '', $domain = 'messages'); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/PluralizationRules.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/PluralizationRules.php new file mode 100644 index 0000000..77c2760 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/PluralizationRules.php @@ -0,0 +1,218 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +/** + * Returns the plural rules for a given locale. + * + * @author Fabien Potencier + * + * @deprecated since Symfony 4.2, use IdentityTranslator instead + */ +class PluralizationRules +{ + private static $rules = []; + + /** + * Returns the plural position to use for the given locale and number. + * + * @param int $number The number + * @param string $locale The locale + * + * @return int The plural position + */ + public static function get($number, $locale/*, bool $triggerDeprecation = true*/) + { + if (3 > \func_num_args() || func_get_arg(2)) { + @trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED); + } + + if ('pt_BR' === $locale) { + // temporary set a locale for brazilian + $locale = 'xbr'; + } + + if (\strlen($locale) > 3) { + $locale = substr($locale, 0, -\strlen(strrchr($locale, '_'))); + } + + if (isset(self::$rules[$locale])) { + $return = self::$rules[$locale]($number); + + if (!\is_int($return) || $return < 0) { + return 0; + } + + return $return; + } + + /* + * The plural rules are derived from code of the Zend Framework (2010-09-25), + * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd). + * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + */ + switch ($locale) { + case 'az': + case 'bo': + case 'dz': + case 'id': + case 'ja': + case 'jv': + case 'ka': + case 'km': + case 'kn': + case 'ko': + case 'ms': + case 'th': + case 'tr': + case 'vi': + case 'zh': + return 0; + + case 'af': + case 'bn': + case 'bg': + case 'ca': + case 'da': + case 'de': + case 'el': + case 'en': + case 'eo': + case 'es': + case 'et': + case 'eu': + case 'fa': + case 'fi': + case 'fo': + case 'fur': + case 'fy': + case 'gl': + case 'gu': + case 'ha': + case 'he': + case 'hu': + case 'is': + case 'it': + case 'ku': + case 'lb': + case 'ml': + case 'mn': + case 'mr': + case 'nah': + case 'nb': + case 'ne': + case 'nl': + case 'nn': + case 'no': + case 'oc': + case 'om': + case 'or': + case 'pa': + case 'pap': + case 'ps': + case 'pt': + case 'so': + case 'sq': + case 'sv': + case 'sw': + case 'ta': + case 'te': + case 'tk': + case 'ur': + case 'zu': + return (1 == $number) ? 0 : 1; + + case 'am': + case 'bh': + case 'fil': + case 'fr': + case 'gun': + case 'hi': + case 'hy': + case 'ln': + case 'mg': + case 'nso': + case 'xbr': + case 'ti': + case 'wa': + return ((0 == $number) || (1 == $number)) ? 0 : 1; + + case 'be': + case 'bs': + case 'hr': + case 'ru': + case 'sh': + case 'sr': + case 'uk': + return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); + + case 'cs': + case 'sk': + return (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); + + case 'ga': + return (1 == $number) ? 0 : ((2 == $number) ? 1 : 2); + + case 'lt': + return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); + + case 'sl': + return (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3)); + + case 'mk': + return (1 == $number % 10) ? 0 : 1; + + case 'mt': + return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); + + case 'lv': + return (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2); + + case 'pl': + return (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); + + case 'cy': + return (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3)); + + case 'ro': + return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); + + case 'ar': + return (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5)))); + + default: + return 0; + } + } + + /** + * Overrides the default plural rule for a given locale. + * + * @param callable $rule A PHP callable + * @param string $locale The locale + */ + public static function set(callable $rule, $locale) + { + @trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED); + + if ('pt_BR' === $locale) { + // temporary set a locale for brazilian + $locale = 'xbr'; + } + + if (\strlen($locale) > 3) { + $locale = substr($locale, 0, -\strlen(strrchr($locale, '_'))); + } + + self::$rules[$locale] = $rule; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/README.md b/plugins/vdomah/jwtauth/vendor/symfony/translation/README.md new file mode 100644 index 0000000..f4f1706 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/README.md @@ -0,0 +1,31 @@ +Translation Component +===================== + +The Translation component provides tools to internationalize your application. + +Getting Started +--------------- + +``` +$ composer require symfony/translation +``` + +```php +use Symfony\Component\Translation\Translator; + +$translator = new Translator('fr_FR'); +$translator->addResource('array', [ + 'Hello World!' => 'Bonjour !', +], 'fr_FR'); + +echo $translator->trans('Hello World!'); // outputs « Bonjour ! » +``` + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/translation.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Reader/TranslationReader.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Reader/TranslationReader.php new file mode 100644 index 0000000..2b98345 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Reader/TranslationReader.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Reader; + +use Symfony\Component\Finder\Finder; +use Symfony\Component\Translation\Loader\LoaderInterface; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * TranslationReader reads translation messages from translation files. + * + * @author Michel Salib + */ +class TranslationReader implements TranslationReaderInterface +{ + /** + * Loaders used for import. + * + * @var array + */ + private $loaders = []; + + /** + * Adds a loader to the translation extractor. + * + * @param string $format The format of the loader + */ + public function addLoader($format, LoaderInterface $loader) + { + $this->loaders[$format] = $loader; + } + + /** + * {@inheritdoc} + */ + public function read($directory, MessageCatalogue $catalogue) + { + if (!is_dir($directory)) { + return; + } + + foreach ($this->loaders as $format => $loader) { + // load any existing translation files + $finder = new Finder(); + $extension = $catalogue->getLocale().'.'.$format; + $files = $finder->files()->name('*.'.$extension)->in($directory); + foreach ($files as $file) { + $domain = substr($file->getFilename(), 0, -1 * \strlen($extension) - 1); + $catalogue->addCatalogue($loader->load($file->getPathname(), $catalogue->getLocale(), $domain)); + } + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Reader/TranslationReaderInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Reader/TranslationReaderInterface.php new file mode 100644 index 0000000..0b2ad33 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Reader/TranslationReaderInterface.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Reader; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * TranslationReader reads translation messages from translation files. + * + * @author Tobias Nyholm + */ +interface TranslationReaderInterface +{ + /** + * Reads translation messages from a directory to the catalogue. + * + * @param string $directory + */ + public function read($directory, MessageCatalogue $catalogue); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/bin/translation-status.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/bin/translation-status.php new file mode 100644 index 0000000..44918c9 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/bin/translation-status.php @@ -0,0 +1,207 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +$usageInstructions = << false, + // NULL = analyze all locales + 'locale_to_analyze' => null, + // the reference files all the other translations are compared to + 'original_files' => [ + 'src/Symfony/Component/Form/Resources/translations/validators.en.xlf', + 'src/Symfony/Component/Security/Core/Resources/translations/security.en.xlf', + 'src/Symfony/Component/Validator/Resources/translations/validators.en.xlf', + ], +]; + +$argc = $_SERVER['argc']; +$argv = $_SERVER['argv']; + +if ($argc > 3) { + echo str_replace('translation-status.php', $argv[0], $usageInstructions); + exit(1); +} + +foreach (array_slice($argv, 1) as $argumentOrOption) { + if (0 === strpos($argumentOrOption, '-')) { + $config['verbose_output'] = true; + } else { + $config['locale_to_analyze'] = $argumentOrOption; + } +} + +foreach ($config['original_files'] as $originalFilePath) { + if (!file_exists($originalFilePath)) { + echo sprintf('The following file does not exist. Make sure that you execute this command at the root dir of the Symfony code repository.%s %s', PHP_EOL, $originalFilePath); + exit(1); + } +} + +$totalMissingTranslations = 0; + +foreach ($config['original_files'] as $originalFilePath) { + $translationFilePaths = findTranslationFiles($originalFilePath, $config['locale_to_analyze']); + $translationStatus = calculateTranslationStatus($originalFilePath, $translationFilePaths); + + $totalMissingTranslations += array_sum(array_map(function ($translation) { + return count($translation['missingKeys']); + }, array_values($translationStatus))); + + printTranslationStatus($originalFilePath, $translationStatus, $config['verbose_output']); +} + +exit($totalMissingTranslations > 0 ? 1 : 0); + +function findTranslationFiles($originalFilePath, $localeToAnalyze) +{ + $translations = []; + + $translationsDir = dirname($originalFilePath); + $originalFileName = basename($originalFilePath); + $translationFileNamePattern = str_replace('.en.', '.*.', $originalFileName); + + $translationFiles = glob($translationsDir.'/'.$translationFileNamePattern, GLOB_NOSORT); + sort($translationFiles); + foreach ($translationFiles as $filePath) { + $locale = extractLocaleFromFilePath($filePath); + + if (null !== $localeToAnalyze && $locale !== $localeToAnalyze) { + continue; + } + + $translations[$locale] = $filePath; + } + + return $translations; +} + +function calculateTranslationStatus($originalFilePath, $translationFilePaths) +{ + $translationStatus = []; + $allTranslationKeys = extractTranslationKeys($originalFilePath); + + foreach ($translationFilePaths as $locale => $translationPath) { + $translatedKeys = extractTranslationKeys($translationPath); + $missingKeys = array_diff_key($allTranslationKeys, $translatedKeys); + + $translationStatus[$locale] = [ + 'total' => count($allTranslationKeys), + 'translated' => count($translatedKeys), + 'missingKeys' => $missingKeys, + ]; + } + + return $translationStatus; +} + +function printTranslationStatus($originalFilePath, $translationStatus, $verboseOutput) +{ + printTitle($originalFilePath); + printTable($translationStatus, $verboseOutput); + echo PHP_EOL.PHP_EOL; +} + +function extractLocaleFromFilePath($filePath) +{ + $parts = explode('.', $filePath); + + return $parts[count($parts) - 2]; +} + +function extractTranslationKeys($filePath) +{ + $translationKeys = []; + $contents = new \SimpleXMLElement(file_get_contents($filePath)); + + foreach ($contents->file->body->{'trans-unit'} as $translationKey) { + $translationId = (string) $translationKey['id']; + $translationKey = (string) $translationKey->source; + + $translationKeys[$translationId] = $translationKey; + } + + return $translationKeys; +} + +function printTitle($title) +{ + echo $title.PHP_EOL; + echo str_repeat('=', strlen($title)).PHP_EOL.PHP_EOL; +} + +function printTable($translations, $verboseOutput) +{ + if (0 === count($translations)) { + echo 'No translations found'; + + return; + } + $longestLocaleNameLength = max(array_map('strlen', array_keys($translations))); + + foreach ($translations as $locale => $translation) { + if ($translation['translated'] > $translation['total']) { + textColorRed(); + } elseif ($translation['translated'] === $translation['total']) { + textColorGreen(); + } + + echo sprintf('| Locale: %-'.$longestLocaleNameLength.'s | Translated: %d/%d', $locale, $translation['translated'], $translation['total']).PHP_EOL; + + textColorNormal(); + + if (true === $verboseOutput && count($translation['missingKeys']) > 0) { + echo str_repeat('-', 80).PHP_EOL; + echo '| Missing Translations:'.PHP_EOL; + + foreach ($translation['missingKeys'] as $id => $content) { + echo sprintf('| (id=%s) %s', $id, $content).PHP_EOL; + } + + echo str_repeat('-', 80).PHP_EOL; + } + } +} + +function textColorGreen() +{ + echo "\033[32m"; +} + +function textColorRed() +{ + echo "\033[31m"; +} + +function textColorNormal() +{ + echo "\033[0m"; +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/data/parents.json b/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/data/parents.json new file mode 100644 index 0000000..6e45d9f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/data/parents.json @@ -0,0 +1,136 @@ +{ + "az_Cyrl": "root", + "bs_Cyrl": "root", + "en_150": "en_001", + "en_AG": "en_001", + "en_AI": "en_001", + "en_AT": "en_150", + "en_AU": "en_001", + "en_BB": "en_001", + "en_BE": "en_150", + "en_BM": "en_001", + "en_BS": "en_001", + "en_BW": "en_001", + "en_BZ": "en_001", + "en_CA": "en_001", + "en_CC": "en_001", + "en_CH": "en_150", + "en_CK": "en_001", + "en_CM": "en_001", + "en_CX": "en_001", + "en_CY": "en_001", + "en_DE": "en_150", + "en_DG": "en_001", + "en_DK": "en_150", + "en_DM": "en_001", + "en_ER": "en_001", + "en_FI": "en_150", + "en_FJ": "en_001", + "en_FK": "en_001", + "en_FM": "en_001", + "en_GB": "en_001", + "en_GD": "en_001", + "en_GG": "en_001", + "en_GH": "en_001", + "en_GI": "en_001", + "en_GM": "en_001", + "en_GY": "en_001", + "en_HK": "en_001", + "en_IE": "en_001", + "en_IL": "en_001", + "en_IM": "en_001", + "en_IN": "en_001", + "en_IO": "en_001", + "en_JE": "en_001", + "en_JM": "en_001", + "en_KE": "en_001", + "en_KI": "en_001", + "en_KN": "en_001", + "en_KY": "en_001", + "en_LC": "en_001", + "en_LR": "en_001", + "en_LS": "en_001", + "en_MG": "en_001", + "en_MO": "en_001", + "en_MS": "en_001", + "en_MT": "en_001", + "en_MU": "en_001", + "en_MW": "en_001", + "en_MY": "en_001", + "en_NA": "en_001", + "en_NF": "en_001", + "en_NG": "en_001", + "en_NL": "en_150", + "en_NR": "en_001", + "en_NU": "en_001", + "en_NZ": "en_001", + "en_PG": "en_001", + "en_PH": "en_001", + "en_PK": "en_001", + "en_PN": "en_001", + "en_PW": "en_001", + "en_RW": "en_001", + "en_SB": "en_001", + "en_SC": "en_001", + "en_SD": "en_001", + "en_SE": "en_150", + "en_SG": "en_001", + "en_SH": "en_001", + "en_SI": "en_150", + "en_SL": "en_001", + "en_SS": "en_001", + "en_SX": "en_001", + "en_SZ": "en_001", + "en_TC": "en_001", + "en_TK": "en_001", + "en_TO": "en_001", + "en_TT": "en_001", + "en_TV": "en_001", + "en_TZ": "en_001", + "en_UG": "en_001", + "en_VC": "en_001", + "en_VG": "en_001", + "en_VU": "en_001", + "en_WS": "en_001", + "en_ZA": "en_001", + "en_ZM": "en_001", + "en_ZW": "en_001", + "es_AR": "es_419", + "es_BO": "es_419", + "es_BR": "es_419", + "es_BZ": "es_419", + "es_CL": "es_419", + "es_CO": "es_419", + "es_CR": "es_419", + "es_CU": "es_419", + "es_DO": "es_419", + "es_EC": "es_419", + "es_GT": "es_419", + "es_HN": "es_419", + "es_MX": "es_419", + "es_NI": "es_419", + "es_PA": "es_419", + "es_PE": "es_419", + "es_PR": "es_419", + "es_PY": "es_419", + "es_SV": "es_419", + "es_US": "es_419", + "es_UY": "es_419", + "es_VE": "es_419", + "pa_Arab": "root", + "pt_AO": "pt_PT", + "pt_CH": "pt_PT", + "pt_CV": "pt_PT", + "pt_GQ": "pt_PT", + "pt_GW": "pt_PT", + "pt_LU": "pt_PT", + "pt_MO": "pt_PT", + "pt_MZ": "pt_PT", + "pt_ST": "pt_PT", + "pt_TL": "pt_PT", + "sr_Latn": "root", + "uz_Arab": "root", + "uz_Cyrl": "root", + "zh_Hant": "root", + "zh_Hant_MO": "zh_Hant_HK" +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd b/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd new file mode 100644 index 0000000..dface62 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd @@ -0,0 +1,2223 @@ + + + + + + + + + + + + + + + Values for the attribute 'context-type'. + + + + + Indicates a database content. + + + + + Indicates the content of an element within an XML document. + + + + + Indicates the name of an element within an XML document. + + + + + Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found. + + + + + Indicates a the number of parameters contained within the <source>. + + + + + Indicates notes pertaining to the parameters in the <source>. + + + + + Indicates the content of a record within a database. + + + + + Indicates the name of a record within a database. + + + + + Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file. + + + + + + + Values for the attribute 'count-type'. + + + + + Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts. + + + + + Indicates the count units are translation units existing already in the same document. + + + + + Indicates a total count. + + + + + + + Values for the attribute 'ctype' when used other elements than <ph> or <x>. + + + + + Indicates a run of bolded text. + + + + + Indicates a run of text in italics. + + + + + Indicates a run of underlined text. + + + + + Indicates a run of hyper-text. + + + + + + + Values for the attribute 'ctype' when used with <ph> or <x>. + + + + + Indicates a inline image. + + + + + Indicates a page break. + + + + + Indicates a line break. + + + + + + + + + + + + Values for the attribute 'datatype'. + + + + + Indicates Active Server Page data. + + + + + Indicates C source file data. + + + + + Indicates Channel Definition Format (CDF) data. + + + + + Indicates ColdFusion data. + + + + + Indicates C++ source file data. + + + + + Indicates C-Sharp data. + + + + + Indicates strings from C, ASM, and driver files data. + + + + + Indicates comma-separated values data. + + + + + Indicates database data. + + + + + Indicates portions of document that follows data and contains metadata. + + + + + Indicates portions of document that precedes data and contains metadata. + + + + + Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import). + + + + + Indicates standard user input screen data. + + + + + Indicates HyperText Markup Language (HTML) data - document instance. + + + + + Indicates content within an HTML document’s <body> element. + + + + + Indicates Windows INI file data. + + + + + Indicates Interleaf data. + + + + + Indicates Java source file data (extension '.java'). + + + + + Indicates Java property resource bundle data. + + + + + Indicates Java list resource bundle data. + + + + + Indicates JavaScript source file data. + + + + + Indicates JScript source file data. + + + + + Indicates information relating to formatting. + + + + + Indicates LISP source file data. + + + + + Indicates information relating to margin formats. + + + + + Indicates a file containing menu. + + + + + Indicates numerically identified string table. + + + + + Indicates Maker Interchange Format (MIF) data. + + + + + Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute. + + + + + Indicates GNU Machine Object data. + + + + + Indicates Message Librarian strings created by Novell's Message Librarian Tool. + + + + + Indicates information to be displayed at the bottom of each page of a document. + + + + + Indicates information to be displayed at the top of each page of a document. + + + + + Indicates a list of property values (e.g., settings within INI files or preferences dialog). + + + + + Indicates Pascal source file data. + + + + + Indicates Hypertext Preprocessor data. + + + + + Indicates plain text file (no formatting other than, possibly, wrapping). + + + + + Indicates GNU Portable Object file. + + + + + Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc. + + + + + Indicates Windows .NET binary resources. + + + + + Indicates Windows .NET Resources. + + + + + Indicates Rich Text Format (RTF) data. + + + + + Indicates Standard Generalized Markup Language (SGML) data - document instance. + + + + + Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD). + + + + + Indicates Scalable Vector Graphic (SVG) data. + + + + + Indicates VisualBasic Script source file. + + + + + Indicates warning message. + + + + + Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file). + + + + + Indicates Extensible HyperText Markup Language (XHTML) data - document instance. + + + + + Indicates Extensible Markup Language (XML) data - document instance. + + + + + Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD). + + + + + Indicates Extensible Stylesheet Language (XSL) data. + + + + + Indicates XUL elements. + + + + + + + Values for the attribute 'mtype'. + + + + + Indicates the marked text is an abbreviation. + + + + + ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept. + + + + + ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective'). + + + + + ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging'). + + + + + ISO-12620: A proper-name term, such as the name of an agency or other proper entity. + + + + + ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another. + + + + + ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language. + + + + + Indicates the marked text is a date and/or time. + + + + + ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign. + + + + + ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form. + + + + + ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula. + + + + + ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record. + + + + + ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy'). + + + + + ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body. + + + + + ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages. + + + + + ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like. + + + + + ISO-12620 2.1.17: A unit to track object. + + + + + Indicates the marked text is a name. + + + + + ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others. + + + + + ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system. + + + + + Indicates the marked text is a phrase. + + + + + ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase. + + + + + Indicates the marked text should not be translated. + + + + + ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet. + + + + + Indicates that the marked text represents a segment. + + + + + ISO-12620 2.1.18.2: A fixed, lexicalized phrase. + + + + + ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs'). + + + + + ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system. + + + + + ISO-12620 2.1.19: A fixed chunk of recurring text. + + + + + ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof. + + + + + ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry. + + + + + ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language. + + + + + Indicates the marked text is a term. + + + + + ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted. + + + + + ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system. + + + + + ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza'). + + + + + ISO-12620 2.1.9: One of the alternate forms of a term. + + + + + + + Values for the attribute 'restype'. + + + + + Indicates a Windows RC AUTO3STATE control. + + + + + Indicates a Windows RC AUTOCHECKBOX control. + + + + + Indicates a Windows RC AUTORADIOBUTTON control. + + + + + Indicates a Windows RC BEDIT control. + + + + + Indicates a bitmap, for example a BITMAP resource in Windows. + + + + + Indicates a button object, for example a BUTTON control Windows. + + + + + Indicates a caption, such as the caption of a dialog box. + + + + + Indicates the cell in a table, for example the content of the <td> element in HTML. + + + + + Indicates check box object, for example a CHECKBOX control in Windows. + + + + + Indicates a menu item with an associated checkbox. + + + + + Indicates a list box, but with a check-box for each item. + + + + + Indicates a color selection dialog. + + + + + Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows. + + + + + Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234). + + + + + Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403). + + + + + Indicates a UI base class element that cannot be represented by any other element. + + + + + Indicates a context menu. + + + + + Indicates a Windows RC CTEXT control. + + + + + Indicates a cursor, for example a CURSOR resource in Windows. + + + + + Indicates a date/time picker. + + + + + Indicates a Windows RC DEFPUSHBUTTON control. + + + + + Indicates a dialog box. + + + + + Indicates a Windows RC DLGINIT resource block. + + + + + Indicates an edit box object, for example an EDIT control in Windows. + + + + + Indicates a filename. + + + + + Indicates a file dialog. + + + + + Indicates a footnote. + + + + + Indicates a font name. + + + + + Indicates a footer. + + + + + Indicates a frame object. + + + + + Indicates a XUL grid element. + + + + + Indicates a groupbox object, for example a GROUPBOX control in Windows. + + + + + Indicates a header item. + + + + + Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML. + + + + + Indicates a Windows RC HEDIT control. + + + + + Indicates a horizontal scrollbar. + + + + + Indicates an icon, for example an ICON resource in Windows. + + + + + Indicates a Windows RC IEDIT control. + + + + + Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF. + + + + + Indicates a label object. + + + + + Indicates a label that is also a HTML link (not necessarily a URL). + + + + + Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML). + + + + + Indicates a listbox object, for example an LISTBOX control in Windows. + + + + + Indicates an list item (an entry in a list). + + + + + Indicates a Windows RC LTEXT control. + + + + + Indicates a menu (a group of menu-items). + + + + + Indicates a toolbar containing one or more tope level menus. + + + + + Indicates a menu item (an entry in a menu). + + + + + Indicates a XUL menuseparator element. + + + + + Indicates a message, for example an entry in a MESSAGETABLE resource in Windows. + + + + + Indicates a calendar control. + + + + + Indicates an edit box beside a spin control. + + + + + Indicates a catch all for rectangular areas. + + + + + Indicates a standalone menu not necessarily associated with a menubar. + + + + + Indicates a pushbox object, for example a PUSHBOX control in Windows. + + + + + Indicates a Windows RC PUSHBUTTON control. + + + + + Indicates a radio button object. + + + + + Indicates a menuitem with associated radio button. + + + + + Indicates raw data resources for an application. + + + + + Indicates a row in a table. + + + + + Indicates a Windows RC RTEXT control. + + + + + Indicates a user navigable container used to show a portion of a document. + + + + + Indicates a generic divider object (e.g. menu group separator). + + + + + Windows accelerators, shortcuts in resource or property files. + + + + + Indicates a UI control to indicate process activity but not progress. + + + + + Indicates a splitter bar. + + + + + Indicates a Windows RC STATE3 control. + + + + + Indicates a window for providing feedback to the users, like 'read-only', etc. + + + + + Indicates a string, for example an entry in a STRINGTABLE resource in Windows. + + + + + Indicates a layers of controls with a tab to select layers. + + + + + Indicates a display and edits regular two-dimensional tables of cells. + + + + + Indicates a XUL textbox element. + + + + + Indicates a UI button that can be toggled to on or off state. + + + + + Indicates an array of controls, usually buttons. + + + + + Indicates a pop up tool tip text. + + + + + Indicates a bar with a pointer indicating a position within a certain range. + + + + + Indicates a control that displays a set of hierarchical data. + + + + + Indicates a URI (URN or URL). + + + + + Indicates a Windows RC USERBUTTON control. + + + + + Indicates a user-defined control like CONTROL control in Windows. + + + + + Indicates the text of a variable. + + + + + Indicates version information about a resource like VERSIONINFO in Windows. + + + + + Indicates a vertical scrollbar. + + + + + Indicates a graphical window. + + + + + + + Values for the attribute 'size-unit'. + + + + + Indicates a size in 8-bit bytes. + + + + + Indicates a size in Unicode characters. + + + + + Indicates a size in columns. Used for HTML text area. + + + + + Indicates a size in centimeters. + + + + + Indicates a size in dialog units, as defined in Windows resources. + + + + + Indicates a size in 'font-size' units (as defined in CSS). + + + + + Indicates a size in 'x-height' units (as defined in CSS). + + + + + Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster' + + + + + Indicates a size in inches. + + + + + Indicates a size in millimeters. + + + + + Indicates a size in percentage. + + + + + Indicates a size in pixels. + + + + + Indicates a size in point. + + + + + Indicates a size in rows. Used for HTML text area. + + + + + + + Values for the attribute 'state'. + + + + + Indicates the terminating state. + + + + + Indicates only non-textual information needs adaptation. + + + + + Indicates both text and non-textual information needs adaptation. + + + + + Indicates only non-textual information needs review. + + + + + Indicates both text and non-textual information needs review. + + + + + Indicates that only the text of the item needs to be reviewed. + + + + + Indicates that the item needs to be translated. + + + + + Indicates that the item is new. For example, translation units that were not in a previous version of the document. + + + + + Indicates that changes are reviewed and approved. + + + + + Indicates that the item has been translated. + + + + + + + Values for the attribute 'state-qualifier'. + + + + + Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously. + + + + + Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.). + + + + + Indicates a match based on matching IDs (in addition to matching text). + + + + + Indicates a translation derived from a glossary. + + + + + Indicates a translation derived from existing translation. + + + + + Indicates a translation derived from machine translation. + + + + + Indicates a translation derived from a translation repository. + + + + + Indicates a translation derived from a translation memory. + + + + + Indicates the translation is suggested by machine translation. + + + + + Indicates that the item has been rejected because of incorrect grammar. + + + + + Indicates that the item has been rejected because it is incorrect. + + + + + Indicates that the item has been rejected because it is too long or too short. + + + + + Indicates that the item has been rejected because of incorrect spelling. + + + + + Indicates the translation is suggested by translation memory. + + + + + + + Values for the attribute 'unit'. + + + + + Refers to words. + + + + + Refers to pages. + + + + + Refers to <trans-unit> elements. + + + + + Refers to <bin-unit> elements. + + + + + Refers to glyphs. + + + + + Refers to <trans-unit> and/or <bin-unit> elements. + + + + + Refers to the occurrences of instances defined by the count-type value. + + + + + Refers to characters. + + + + + Refers to lines. + + + + + Refers to sentences. + + + + + Refers to paragraphs. + + + + + Refers to segments. + + + + + Refers to placeables (inline elements). + + + + + + + Values for the attribute 'priority'. + + + + + Highest priority. + + + + + High priority. + + + + + High priority, but not as important as 2. + + + + + High priority, but not as important as 3. + + + + + Medium priority, but more important than 6. + + + + + Medium priority, but less important than 5. + + + + + Low priority, but more important than 8. + + + + + Low priority, but more important than 9. + + + + + Low priority. + + + + + Lowest priority. + + + + + + + + + This value indicates that all properties can be reformatted. This value must be used alone. + + + + + This value indicates that no properties should be reformatted. This value must be used alone. + + + + + + + + + + + + + This value indicates that all information in the coord attribute can be modified. + + + + + This value indicates that the x information in the coord attribute can be modified. + + + + + This value indicates that the y information in the coord attribute can be modified. + + + + + This value indicates that the cx information in the coord attribute can be modified. + + + + + This value indicates that the cy information in the coord attribute can be modified. + + + + + This value indicates that all the information in the font attribute can be modified. + + + + + This value indicates that the name information in the font attribute can be modified. + + + + + This value indicates that the size information in the font attribute can be modified. + + + + + This value indicates that the weight information in the font attribute can be modified. + + + + + This value indicates that the information in the css-style attribute can be modified. + + + + + This value indicates that the information in the style attribute can be modified. + + + + + This value indicates that the information in the exstyle attribute can be modified. + + + + + + + + + + + + + Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document. + + + + + Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed. + + + + + Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed. + + + + + + + + + Represents a translation proposal from a translation memory or other resource. + + + + + Represents a previous version of the target element. + + + + + Represents a rejected version of the target element. + + + + + Represents a translation to be used for reference purposes only, for example from a related product or a different language. + + + + + Represents a proposed translation that was used for the translation of the trans-unit, possibly modified. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Values for the attribute 'coord'. + + + + + + + + Version values: 1.0 and 1.1 are allowed for backward compatibility. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd b/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd new file mode 100644 index 0000000..963232f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/schemas/xml.xsd b/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/schemas/xml.xsd new file mode 100644 index 0000000..a46162a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Resources/schemas/xml.xsd @@ -0,0 +1,309 @@ + + + + + + +
+

About the XML namespace

+ +
+

+ + This schema document describes the XML namespace, in a form + suitable for import by other schema documents. +

+

+ See + http://www.w3.org/XML/1998/namespace.html and + + http://www.w3.org/TR/REC-xml for information + about this namespace. +

+ +

+ Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. +

+

+ See further below in this document for more information about how to refer to this schema document from your own + XSD schema documents and about the + namespace-versioning policy governing this schema document. +

+
+
+ +
+
+ + + + +
+ +

lang (as an attribute name)

+

+ + denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.

+ +
+
+

Notes

+

+ Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. +

+

+ + See BCP 47 at + http://www.rfc-editor.org/rfc/bcp/bcp47.txt + and the IANA language subtag registry at + + http://www.iana.org/assignments/language-subtag-registry + for further information. +

+

+ + The union allows for the 'un-declaration' of xml:lang with + the empty string. +

+
+
+
+ + + + + + + + + + +
+ + + + + +
+ +

space (as an attribute name)

+

+ denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.

+ +
+
+
+ + + + + + + +
+ + + + +
+ +

base (as an attribute name)

+

+ denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.

+ +

+ See http://www.w3.org/TR/xmlbase/ + for information about this attribute. +

+ +
+
+
+
+ + + + +
+ +

id (as an attribute name)

+

+ + denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.

+ +

+ See http://www.w3.org/TR/xml-id/ + for information about this attribute. +

+
+
+
+ +
+ + + + + + + + + + + +
+ +

Father (in any context at all)

+ +
+

+ denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: +

+
+

+ + In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". +

+
+
+
+
+
+ + + + +
+

About this schema document

+ +
+

+ This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow xml:base, + xml:lang, xml:space or + xml:id attributes on elements they define. +

+ +

+ To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: +

+
+          <schema.. .>
+          .. .
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+     
+

+ or +

+
+
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+     
+

+ Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. +

+
+          <type.. .>
+          .. .
+           <attributeGroup ref="xml:specialAttrs"/>
+     
+

+ will define a type which will schema-validate an instance element + with any of those attributes. +

+ +
+
+
+
+ + + +
+

Versioning policy for this schema document

+ +
+

+ In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + + http://www.w3.org/2009/01/xml.xsd. +

+

+ At the date of issue it can also be found at + + http://www.w3.org/2001/xml.xsd. +

+ +

+ The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at + http://www.w3.org/2001/xml.xsd + + will change accordingly; the version at + + http://www.w3.org/2009/01/xml.xsd + + will not change. +

+

+ + Previous dated (and unchanging) versions of this schema + document are at: +

+ +
+
+
+
+ +
diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Catalogue/AbstractOperationTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Catalogue/AbstractOperationTest.php new file mode 100644 index 0000000..f82b18f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Catalogue/AbstractOperationTest.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Catalogue; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\MessageCatalogueInterface; + +abstract class AbstractOperationTest extends TestCase +{ + public function testGetEmptyDomains() + { + $this->assertEquals( + [], + $this->createOperation( + new MessageCatalogue('en'), + new MessageCatalogue('en') + )->getDomains() + ); + } + + public function testGetMergedDomains() + { + $this->assertEquals( + ['a', 'b', 'c'], + $this->createOperation( + new MessageCatalogue('en', ['a' => [], 'b' => []]), + new MessageCatalogue('en', ['b' => [], 'c' => []]) + )->getDomains() + ); + } + + public function testGetMessagesFromUnknownDomain() + { + $this->expectException('InvalidArgumentException'); + $this->createOperation( + new MessageCatalogue('en'), + new MessageCatalogue('en') + )->getMessages('domain'); + } + + public function testGetEmptyMessages() + { + $this->assertEquals( + [], + $this->createOperation( + new MessageCatalogue('en', ['a' => []]), + new MessageCatalogue('en') + )->getMessages('a') + ); + } + + public function testGetEmptyResult() + { + $this->assertEquals( + new MessageCatalogue('en'), + $this->createOperation( + new MessageCatalogue('en'), + new MessageCatalogue('en') + )->getResult() + ); + } + + abstract protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Catalogue/MergeOperationTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Catalogue/MergeOperationTest.php new file mode 100644 index 0000000..22af86e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Catalogue/MergeOperationTest.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Catalogue; + +use Symfony\Component\Translation\Catalogue\MergeOperation; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\MessageCatalogueInterface; + +class MergeOperationTest extends AbstractOperationTest +{ + public function testGetMessagesFromSingleDomain() + { + $operation = $this->createOperation( + new MessageCatalogue('en', ['messages' => ['a' => 'old_a', 'b' => 'old_b']]), + new MessageCatalogue('en', ['messages' => ['a' => 'new_a', 'c' => 'new_c']]) + ); + + $this->assertEquals( + ['a' => 'old_a', 'b' => 'old_b', 'c' => 'new_c'], + $operation->getMessages('messages') + ); + + $this->assertEquals( + ['c' => 'new_c'], + $operation->getNewMessages('messages') + ); + + $this->assertEquals( + [], + $operation->getObsoleteMessages('messages') + ); + } + + public function testGetResultFromSingleDomain() + { + $this->assertEquals( + new MessageCatalogue('en', [ + 'messages' => ['a' => 'old_a', 'b' => 'old_b', 'c' => 'new_c'], + ]), + $this->createOperation( + new MessageCatalogue('en', ['messages' => ['a' => 'old_a', 'b' => 'old_b']]), + new MessageCatalogue('en', ['messages' => ['a' => 'new_a', 'c' => 'new_c']]) + )->getResult() + ); + } + + public function testGetResultFromIntlDomain() + { + $this->assertEquals( + new MessageCatalogue('en', [ + 'messages' => ['a' => 'old_a', 'b' => 'old_b'], + 'messages+intl-icu' => ['d' => 'old_d', 'c' => 'new_c'], + ]), + $this->createOperation( + new MessageCatalogue('en', ['messages' => ['a' => 'old_a', 'b' => 'old_b'], 'messages+intl-icu' => ['d' => 'old_d']]), + new MessageCatalogue('en', ['messages+intl-icu' => ['a' => 'new_a', 'c' => 'new_c']]) + )->getResult() + ); + } + + public function testGetResultWithMetadata() + { + $leftCatalogue = new MessageCatalogue('en', ['messages' => ['a' => 'old_a', 'b' => 'old_b']]); + $leftCatalogue->setMetadata('a', 'foo', 'messages'); + $leftCatalogue->setMetadata('b', 'bar', 'messages'); + $rightCatalogue = new MessageCatalogue('en', ['messages' => ['b' => 'new_b', 'c' => 'new_c']]); + $rightCatalogue->setMetadata('b', 'baz', 'messages'); + $rightCatalogue->setMetadata('c', 'qux', 'messages'); + + $mergedCatalogue = new MessageCatalogue('en', ['messages' => ['a' => 'old_a', 'b' => 'old_b', 'c' => 'new_c']]); + $mergedCatalogue->setMetadata('a', 'foo', 'messages'); + $mergedCatalogue->setMetadata('b', 'bar', 'messages'); + $mergedCatalogue->setMetadata('c', 'qux', 'messages'); + + $this->assertEquals( + $mergedCatalogue, + $this->createOperation( + $leftCatalogue, + $rightCatalogue + )->getResult() + ); + } + + protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target) + { + return new MergeOperation($source, $target); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Catalogue/TargetOperationTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Catalogue/TargetOperationTest.php new file mode 100644 index 0000000..d4608f6 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Catalogue/TargetOperationTest.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Catalogue; + +use Symfony\Component\Translation\Catalogue\TargetOperation; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\MessageCatalogueInterface; + +class TargetOperationTest extends AbstractOperationTest +{ + public function testGetMessagesFromSingleDomain() + { + $operation = $this->createOperation( + new MessageCatalogue('en', ['messages' => ['a' => 'old_a', 'b' => 'old_b']]), + new MessageCatalogue('en', ['messages' => ['a' => 'new_a', 'c' => 'new_c']]) + ); + + $this->assertEquals( + ['a' => 'old_a', 'c' => 'new_c'], + $operation->getMessages('messages') + ); + + $this->assertEquals( + ['c' => 'new_c'], + $operation->getNewMessages('messages') + ); + + $this->assertEquals( + ['b' => 'old_b'], + $operation->getObsoleteMessages('messages') + ); + } + + public function testGetResultFromSingleDomain() + { + $this->assertEquals( + new MessageCatalogue('en', [ + 'messages' => ['a' => 'old_a', 'c' => 'new_c'], + ]), + $this->createOperation( + new MessageCatalogue('en', ['messages' => ['a' => 'old_a', 'b' => 'old_b']]), + new MessageCatalogue('en', ['messages' => ['a' => 'new_a', 'c' => 'new_c']]) + )->getResult() + ); + } + + public function testGetResultFromIntlDomain() + { + $this->assertEquals( + new MessageCatalogue('en', [ + 'messages' => ['a' => 'old_a'], + 'messages+intl-icu' => ['c' => 'new_c'], + ]), + $this->createOperation( + new MessageCatalogue('en', ['messages' => ['a' => 'old_a'], 'messages+intl-icu' => ['b' => 'old_b']]), + new MessageCatalogue('en', ['messages' => ['a' => 'new_a'], 'messages+intl-icu' => ['c' => 'new_c']]) + )->getResult() + ); + } + + public function testGetResultWithMixedDomains() + { + $this->assertEquals( + new MessageCatalogue('en', [ + 'messages+intl-icu' => ['a' => 'old_a'], + ]), + $this->createOperation( + new MessageCatalogue('en', ['messages' => ['a' => 'old_a']]), + new MessageCatalogue('en', ['messages+intl-icu' => ['a' => 'new_a']]) + )->getResult() + ); + } + + public function testGetResultWithMetadata() + { + $leftCatalogue = new MessageCatalogue('en', ['messages' => ['a' => 'old_a', 'b' => 'old_b']]); + $leftCatalogue->setMetadata('a', 'foo', 'messages'); + $leftCatalogue->setMetadata('b', 'bar', 'messages'); + $rightCatalogue = new MessageCatalogue('en', ['messages' => ['b' => 'new_b', 'c' => 'new_c']]); + $rightCatalogue->setMetadata('b', 'baz', 'messages'); + $rightCatalogue->setMetadata('c', 'qux', 'messages'); + + $diffCatalogue = new MessageCatalogue('en', ['messages' => ['b' => 'old_b', 'c' => 'new_c']]); + $diffCatalogue->setMetadata('b', 'bar', 'messages'); + $diffCatalogue->setMetadata('c', 'qux', 'messages'); + + $this->assertEquals( + $diffCatalogue, + $this->createOperation( + $leftCatalogue, + $rightCatalogue + )->getResult() + ); + } + + protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target) + { + return new TargetOperation($source, $target); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Command/XliffLintCommandTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Command/XliffLintCommandTest.php new file mode 100644 index 0000000..272ee15 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Command/XliffLintCommandTest.php @@ -0,0 +1,199 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Translation\Command\XliffLintCommand; + +/** + * Tests the XliffLintCommand. + * + * @author Javier Eguiluz + */ +class XliffLintCommandTest extends TestCase +{ + private $files; + + public function testLintCorrectFile() + { + $tester = $this->createCommandTester(); + $filename = $this->createFile(); + + $tester->execute( + ['filename' => $filename], + ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false] + ); + + $this->assertEquals(0, $tester->getStatusCode(), 'Returns 0 in case of success'); + $this->assertStringContainsString('OK', trim($tester->getDisplay())); + } + + public function testLintCorrectFiles() + { + $tester = $this->createCommandTester(); + $filename1 = $this->createFile(); + $filename2 = $this->createFile(); + + $tester->execute( + ['filename' => [$filename1, $filename2]], + ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false] + ); + + $this->assertEquals(0, $tester->getStatusCode(), 'Returns 0 in case of success'); + $this->assertStringContainsString('OK', trim($tester->getDisplay())); + } + + /** + * @dataProvider provideStrictFilenames + */ + public function testStrictFilenames($requireStrictFileNames, $fileNamePattern, $targetLanguage, $mustFail) + { + $tester = $this->createCommandTester($requireStrictFileNames); + $filename = $this->createFile('note', $targetLanguage, $fileNamePattern); + + $tester->execute( + ['filename' => $filename], + ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false] + ); + + $this->assertEquals($mustFail ? 1 : 0, $tester->getStatusCode()); + $this->assertStringContainsString($mustFail ? '[WARNING] 0 XLIFF files have valid syntax and 1 contain errors.' : '[OK] All 1 XLIFF files contain valid syntax.', $tester->getDisplay()); + } + + public function testLintIncorrectXmlSyntax() + { + $tester = $this->createCommandTester(); + $filename = $this->createFile('note '); + + $tester->execute(['filename' => $filename], ['decorated' => false]); + + $this->assertEquals(1, $tester->getStatusCode(), 'Returns 1 in case of error'); + $this->assertStringContainsString('Opening and ending tag mismatch: target line 6 and source', trim($tester->getDisplay())); + } + + public function testLintIncorrectTargetLanguage() + { + $tester = $this->createCommandTester(); + $filename = $this->createFile('note', 'es'); + + $tester->execute(['filename' => $filename], ['decorated' => false]); + + $this->assertEquals(1, $tester->getStatusCode(), 'Returns 1 in case of error'); + $this->assertStringContainsString('There is a mismatch between the language included in the file name ("messages.en.xlf") and the "es" value used in the "target-language" attribute of the file.', trim($tester->getDisplay())); + } + + public function testLintTargetLanguageIsCaseInsensitive() + { + $tester = $this->createCommandTester(); + $filename = $this->createFile('note', 'zh-cn', 'messages.zh_CN.xlf'); + + $tester->execute(['filename' => $filename], ['decorated' => false]); + + $this->assertEquals(0, $tester->getStatusCode()); + $this->assertStringContainsString('[OK] All 1 XLIFF files contain valid syntax.', trim($tester->getDisplay())); + } + + public function testLintFileNotReadable() + { + $this->expectException('RuntimeException'); + $tester = $this->createCommandTester(); + $filename = $this->createFile(); + unlink($filename); + + $tester->execute(['filename' => $filename], ['decorated' => false]); + } + + public function testGetHelp() + { + $command = new XliffLintCommand(); + $expected = <<php %command.full_name% dirname + php %command.full_name% dirname --format=json + +EOF; + + $this->assertStringContainsString($expected, $command->getHelp()); + } + + private function createFile($sourceContent = 'note', $targetLanguage = 'en', $fileNamePattern = 'messages.%locale%.xlf'): string + { + $xliffContent = << + + + + + $sourceContent + NOTE + + + + +XLIFF; + + $filename = sprintf('%s/translation-xliff-lint-test/%s', sys_get_temp_dir(), str_replace('%locale%', 'en', $fileNamePattern)); + file_put_contents($filename, $xliffContent); + + $this->files[] = $filename; + + return $filename; + } + + private function createCommandTester($requireStrictFileNames = true, $application = null): CommandTester + { + if (!$application) { + $application = new Application(); + $application->add(new XliffLintCommand(null, null, null, $requireStrictFileNames)); + } + + $command = $application->find('lint:xliff'); + + if ($application) { + $command->setApplication($application); + } + + return new CommandTester($command); + } + + protected function setUp(): void + { + $this->files = []; + @mkdir(sys_get_temp_dir().'/translation-xliff-lint-test'); + } + + protected function tearDown(): void + { + foreach ($this->files as $file) { + if (file_exists($file)) { + unlink($file); + } + } + rmdir(sys_get_temp_dir().'/translation-xliff-lint-test'); + } + + public function provideStrictFilenames() + { + yield [false, 'messages.%locale%.xlf', 'en', false]; + yield [false, 'messages.%locale%.xlf', 'es', true]; + yield [false, '%locale%.messages.xlf', 'en', false]; + yield [false, '%locale%.messages.xlf', 'es', true]; + yield [true, 'messages.%locale%.xlf', 'en', false]; + yield [true, 'messages.%locale%.xlf', 'es', true]; + yield [true, '%locale%.messages.xlf', 'en', true]; + yield [true, '%locale%.messages.xlf', 'es', true]; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DataCollector/TranslationDataCollectorTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DataCollector/TranslationDataCollectorTest.php new file mode 100644 index 0000000..1a600c8 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DataCollector/TranslationDataCollectorTest.php @@ -0,0 +1,150 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\DataCollector; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\DataCollector\TranslationDataCollector; +use Symfony\Component\Translation\DataCollectorTranslator; + +class TranslationDataCollectorTest extends TestCase +{ + protected function setUp(): void + { + if (!class_exists('Symfony\Component\HttpKernel\DataCollector\DataCollector')) { + $this->markTestSkipped('The "DataCollector" is not available'); + } + } + + public function testCollectEmptyMessages() + { + $translator = $this->getTranslator(); + $translator->expects($this->any())->method('getCollectedMessages')->willReturn([]); + + $dataCollector = new TranslationDataCollector($translator); + $dataCollector->lateCollect(); + + $this->assertEquals(0, $dataCollector->getCountMissings()); + $this->assertEquals(0, $dataCollector->getCountFallbacks()); + $this->assertEquals(0, $dataCollector->getCountDefines()); + $this->assertEquals([], $dataCollector->getMessages()->getValue()); + } + + public function testCollect() + { + $collectedMessages = [ + [ + 'id' => 'foo', + 'translation' => 'foo (en)', + 'locale' => 'en', + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_DEFINED, + 'parameters' => [], + 'transChoiceNumber' => null, + ], + [ + 'id' => 'bar', + 'translation' => 'bar (fr)', + 'locale' => 'fr', + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK, + 'parameters' => [], + 'transChoiceNumber' => null, + ], + [ + 'id' => 'choice', + 'translation' => 'choice', + 'locale' => 'en', + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_MISSING, + 'parameters' => ['%count%' => 3], + 'transChoiceNumber' => 3, + ], + [ + 'id' => 'choice', + 'translation' => 'choice', + 'locale' => 'en', + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_MISSING, + 'parameters' => ['%count%' => 3], + 'transChoiceNumber' => 3, + ], + [ + 'id' => 'choice', + 'translation' => 'choice', + 'locale' => 'en', + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_MISSING, + 'parameters' => ['%count%' => 4, '%foo%' => 'bar'], + 'transChoiceNumber' => 4, + ], + ]; + $expectedMessages = [ + [ + 'id' => 'foo', + 'translation' => 'foo (en)', + 'locale' => 'en', + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_DEFINED, + 'count' => 1, + 'parameters' => [], + 'transChoiceNumber' => null, + ], + [ + 'id' => 'bar', + 'translation' => 'bar (fr)', + 'locale' => 'fr', + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK, + 'count' => 1, + 'parameters' => [], + 'transChoiceNumber' => null, + ], + [ + 'id' => 'choice', + 'translation' => 'choice', + 'locale' => 'en', + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_MISSING, + 'count' => 3, + 'parameters' => [ + ['%count%' => 3], + ['%count%' => 3], + ['%count%' => 4, '%foo%' => 'bar'], + ], + 'transChoiceNumber' => 3, + ], + ]; + + $translator = $this->getTranslator(); + $translator->expects($this->any())->method('getCollectedMessages')->willReturn($collectedMessages); + + $dataCollector = new TranslationDataCollector($translator); + $dataCollector->lateCollect(); + + $this->assertEquals(1, $dataCollector->getCountMissings()); + $this->assertEquals(1, $dataCollector->getCountFallbacks()); + $this->assertEquals(1, $dataCollector->getCountDefines()); + + $this->assertEquals($expectedMessages, array_values($dataCollector->getMessages()->getValue(true))); + } + + private function getTranslator() + { + $translator = $this + ->getMockBuilder('Symfony\Component\Translation\DataCollectorTranslator') + ->disableOriginalConstructor() + ->getMock() + ; + + return $translator; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DataCollectorTranslatorTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DataCollectorTranslatorTest.php new file mode 100644 index 0000000..d3de1e2 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DataCollectorTranslatorTest.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\DataCollectorTranslator; +use Symfony\Component\Translation\Loader\ArrayLoader; +use Symfony\Component\Translation\Translator; + +class DataCollectorTranslatorTest extends TestCase +{ + public function testCollectMessages() + { + $collector = $this->createCollector(); + $collector->setFallbackLocales(['fr', 'ru']); + + $collector->trans('foo'); + $collector->trans('bar'); + $collector->trans('choice', ['%count%' => 0]); + $collector->trans('bar_ru'); + $collector->trans('bar_ru', ['foo' => 'bar']); + + $expectedMessages = []; + $expectedMessages[] = [ + 'id' => 'foo', + 'translation' => 'foo (en)', + 'locale' => 'en', + 'fallbackLocale' => null, + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_DEFINED, + 'parameters' => [], + 'transChoiceNumber' => null, + ]; + $expectedMessages[] = [ + 'id' => 'bar', + 'translation' => 'bar (fr)', + 'locale' => 'en', + 'fallbackLocale' => 'fr', + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK, + 'parameters' => [], + 'transChoiceNumber' => null, + ]; + $expectedMessages[] = [ + 'id' => 'choice', + 'translation' => 'choice', + 'locale' => 'en', + 'fallbackLocale' => null, + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_MISSING, + 'parameters' => ['%count%' => 0], + 'transChoiceNumber' => 0, + ]; + $expectedMessages[] = [ + 'id' => 'bar_ru', + 'translation' => 'bar (ru)', + 'locale' => 'en', + 'fallbackLocale' => 'ru', + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK, + 'parameters' => [], + 'transChoiceNumber' => null, + ]; + $expectedMessages[] = [ + 'id' => 'bar_ru', + 'translation' => 'bar (ru)', + 'locale' => 'en', + 'fallbackLocale' => 'ru', + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK, + 'parameters' => ['foo' => 'bar'], + 'transChoiceNumber' => null, + ]; + + $this->assertEquals($expectedMessages, $collector->getCollectedMessages()); + } + + /** + * @group legacy + */ + public function testCollectMessagesTransChoice() + { + $collector = $this->createCollector(); + $collector->setFallbackLocales(['fr', 'ru']); + $collector->transChoice('choice', 0); + + $expectedMessages = []; + + $expectedMessages[] = [ + 'id' => 'choice', + 'translation' => 'choice', + 'locale' => 'en', + 'fallbackLocale' => null, + 'domain' => 'messages', + 'state' => DataCollectorTranslator::MESSAGE_MISSING, + 'parameters' => ['%count%' => 0], + 'transChoiceNumber' => 0, + ]; + + $this->assertEquals($expectedMessages, $collector->getCollectedMessages()); + } + + private function createCollector() + { + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foo (en)'], 'en'); + $translator->addResource('array', ['bar' => 'bar (fr)'], 'fr'); + $translator->addResource('array', ['bar_ru' => 'bar (ru)'], 'ru'); + + return new DataCollectorTranslator($translator); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationDumperPassTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationDumperPassTest.php new file mode 100644 index 0000000..94769e9 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationDumperPassTest.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass; + +class TranslationDumperPassTest extends TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + $writerDefinition = $container->register('translation.writer'); + $container->register('foo.id') + ->addTag('translation.dumper', ['alias' => 'bar.alias']); + + $translationDumperPass = new TranslationDumperPass(); + $translationDumperPass->process($container); + + $this->assertEquals([['addDumper', ['bar.alias', new Reference('foo.id')]]], $writerDefinition->getMethodCalls()); + } + + public function testProcessNoDefinitionFound() + { + $container = new ContainerBuilder(); + + $definitionsBefore = \count($container->getDefinitions()); + $aliasesBefore = \count($container->getAliases()); + + $translationDumperPass = new TranslationDumperPass(); + $translationDumperPass->process($container); + + // the container is untouched (i.e. no new definitions or aliases) + $this->assertCount($definitionsBefore, $container->getDefinitions()); + $this->assertCount($aliasesBefore, $container->getAliases()); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationExtractorPassTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationExtractorPassTest.php new file mode 100644 index 0000000..113536b --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationExtractorPassTest.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass; + +class TranslationExtractorPassTest extends TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + $extractorDefinition = $container->register('translation.extractor'); + $container->register('foo.id') + ->addTag('translation.extractor', ['alias' => 'bar.alias']); + + $translationDumperPass = new TranslationExtractorPass(); + $translationDumperPass->process($container); + + $this->assertEquals([['addExtractor', ['bar.alias', new Reference('foo.id')]]], $extractorDefinition->getMethodCalls()); + } + + public function testProcessNoDefinitionFound() + { + $container = new ContainerBuilder(); + + $definitionsBefore = \count($container->getDefinitions()); + $aliasesBefore = \count($container->getAliases()); + + $translationDumperPass = new TranslationExtractorPass(); + $translationDumperPass->process($container); + + // the container is untouched (i.e. no new definitions or aliases) + $this->assertCount($definitionsBefore, $container->getDefinitions()); + $this->assertCount($aliasesBefore, $container->getAliases()); + } + + public function testProcessMissingAlias() + { + $this->expectException('Symfony\Component\DependencyInjection\Exception\RuntimeException'); + $this->expectExceptionMessage('The alias for the tag "translation.extractor" of service "foo.id" must be set.'); + $container = new ContainerBuilder(); + $container->register('translation.extractor'); + $container->register('foo.id') + ->addTag('translation.extractor', []); + + $translationDumperPass = new TranslationExtractorPass(); + $translationDumperPass->process($container); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationPassTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationPassTest.php new file mode 100644 index 0000000..f62fc85 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationPassTest.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Translation\DependencyInjection\TranslatorPass; + +class TranslationPassTest extends TestCase +{ + public function testValidCollector() + { + $loader = (new Definition()) + ->addTag('translation.loader', ['alias' => 'xliff', 'legacy-alias' => 'xlf']); + + $reader = new Definition(); + + $translator = (new Definition()) + ->setArguments([null, null, null, null]); + + $container = new ContainerBuilder(); + $container->setDefinition('translator.default', $translator); + $container->setDefinition('translation.reader', $reader); + $container->setDefinition('translation.xliff_loader', $loader); + + $pass = new TranslatorPass('translator.default', 'translation.reader'); + $pass->process($container); + + $expectedReader = (new Definition()) + ->addMethodCall('addLoader', ['xliff', new Reference('translation.xliff_loader')]) + ->addMethodCall('addLoader', ['xlf', new Reference('translation.xliff_loader')]) + ; + $this->assertEquals($expectedReader, $reader); + + $expectedLoader = (new Definition()) + ->addTag('translation.loader', ['alias' => 'xliff', 'legacy-alias' => 'xlf']) + ; + $this->assertEquals($expectedLoader, $loader); + + $this->assertSame(['translation.xliff_loader' => ['xliff', 'xlf']], $translator->getArgument(3)); + + $expected = ['translation.xliff_loader' => new ServiceClosureArgument(new Reference('translation.xliff_loader'))]; + $this->assertEquals($expected, $container->getDefinition((string) $translator->getArgument(0))->getArgument(0)); + } + + public function testValidCommandsViewPathsArgument() + { + $container = new ContainerBuilder(); + $container->register('translator.default') + ->setArguments([null, null, null, null]) + ; + $debugCommand = $container->register('console.command.translation_debug') + ->setArguments([null, null, null, null, null, [], []]) + ; + $updateCommand = $container->register('console.command.translation_update') + ->setArguments([null, null, null, null, null, null, [], []]) + ; + $container->register('twig.template_iterator') + ->setArguments([null, null, ['other/templates' => null, 'tpl' => 'App']]) + ; + $container->setParameter('twig.default_path', 'templates'); + + $pass = new TranslatorPass('translator.default'); + $pass->process($container); + + $expectedViewPaths = ['other/templates', 'tpl']; + + $this->assertSame('templates', $debugCommand->getArgument(4)); + $this->assertSame('templates', $updateCommand->getArgument(5)); + $this->assertSame($expectedViewPaths, $debugCommand->getArgument(6)); + $this->assertSame($expectedViewPaths, $updateCommand->getArgument(7)); + } + + public function testCommandsViewPathsArgumentsAreIgnoredWithOldServiceDefinitions() + { + $container = new ContainerBuilder(); + $container->register('translator.default') + ->setArguments([null, null, null, null]) + ; + $debugCommand = $container->register('console.command.translation_debug') + ->setArguments([ + new Reference('translator'), + new Reference('translation.reader'), + new Reference('translation.extractor'), + '%translator.default_path%', + null, + ]) + ; + $updateCommand = $container->register('console.command.translation_update') + ->setArguments([ + new Reference('translation.writer'), + new Reference('translation.reader'), + new Reference('translation.extractor'), + '%kernel.default_locale%', + '%translator.default_path%', + null, + ]) + ; + $container->register('twig.template_iterator') + ->setArguments([null, null, ['other/templates' => null, 'tpl' => 'App']]) + ; + $container->setParameter('twig.default_path', 'templates'); + + $pass = new TranslatorPass('translator.default'); + $pass->process($container); + + $this->assertSame('templates', $debugCommand->getArgument(4)); + $this->assertSame('templates', $updateCommand->getArgument(5)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationPathsPassTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationPathsPassTest.php new file mode 100644 index 0000000..42ab398 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/TranslationPathsPassTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\Translation\DependencyInjection\TranslatorPathsPass; +use Symfony\Component\Translation\Tests\DependencyInjection\fixtures\ControllerArguments; +use Symfony\Component\Translation\Tests\DependencyInjection\fixtures\ServiceArguments; +use Symfony\Component\Translation\Tests\DependencyInjection\fixtures\ServiceMethodCalls; +use Symfony\Component\Translation\Tests\DependencyInjection\fixtures\ServiceProperties; +use Symfony\Component\Translation\Tests\DependencyInjection\fixtures\ServiceSubscriber; + +class TranslationPathsPassTest extends TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + $container->register('translator'); + $debugCommand = $container->register('console.command.translation_debug') + ->setArguments([null, null, null, null, null, [], []]) + ; + $updateCommand = $container->register('console.command.translation_update') + ->setArguments([null, null, null, null, null, null, [], []]) + ; + $container->register(ControllerArguments::class, ControllerArguments::class) + ->setTags(['controller.service_arguments']) + ; + $container->register(ServiceArguments::class, ServiceArguments::class) + ->setArguments([new Reference('translator')]) + ; + $container->register(ServiceProperties::class, ServiceProperties::class) + ->setProperties([new Reference('translator')]) + ; + $container->register(ServiceMethodCalls::class, ServiceMethodCalls::class) + ->setMethodCalls([['setTranslator', [new Reference('translator')]]]) + ; + $container->register('service_rc') + ->setArguments([new Definition(), new Reference(ServiceMethodCalls::class)]) + ; + $serviceLocator1 = $container->register('.service_locator.foo', ServiceLocator::class) + ->setArguments([new ServiceClosureArgument(new Reference('translator'))]) + ; + $serviceLocator2 = (new Definition(ServiceLocator::class)) + ->setArguments([ServiceSubscriber::class, new Reference('service_container')]) + ->setFactory([$serviceLocator1, 'withContext']) + ; + $container->register('service_subscriber', ServiceSubscriber::class) + ->setArguments([$serviceLocator2]) + ; + $container->register('.service_locator.bar', ServiceLocator::class) + ->setArguments([[ + ControllerArguments::class.'::index' => new ServiceClosureArgument(new Reference('.service_locator.foo')), + ControllerArguments::class.'::__invoke' => new ServiceClosureArgument(new Reference('.service_locator.foo')), + ControllerArguments::class => new ServiceClosureArgument(new Reference('.service_locator.foo')), + ]]) + ; + $container->register('argument_resolver.service') + ->setArguments([new Reference('.service_locator.bar')]) + ; + + $pass = new TranslatorPathsPass('translator', 'console.command.translation_debug', 'console.command.translation_update', 'argument_resolver.service'); + $pass->process($container); + + $expectedPaths = [ + $container->getReflectionClass(ServiceArguments::class)->getFileName(), + $container->getReflectionClass(ServiceProperties::class)->getFileName(), + $container->getReflectionClass(ServiceMethodCalls::class)->getFileName(), + $container->getReflectionClass(ControllerArguments::class)->getFileName(), + $container->getReflectionClass(ServiceSubscriber::class)->getFileName(), + ]; + + $this->assertSame($expectedPaths, $debugCommand->getArgument(6)); + $this->assertSame($expectedPaths, $updateCommand->getArgument(7)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/fixtures/ControllerArguments.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/fixtures/ControllerArguments.php new file mode 100644 index 0000000..97a53fa --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/DependencyInjection/fixtures/ControllerArguments.php @@ -0,0 +1,16 @@ + TranslatorInterface::class]; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/CsvFileDumperTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/CsvFileDumperTest.php new file mode 100644 index 0000000..0d1cf2c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/CsvFileDumperTest.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\CsvFileDumper; +use Symfony\Component\Translation\MessageCatalogue; + +class CsvFileDumperTest extends TestCase +{ + public function testFormatCatalogue() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => 'bar', 'bar' => 'foo +foo', 'foo;foo' => 'bar']); + + $dumper = new CsvFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/valid.csv', $dumper->formatCatalogue($catalogue, 'messages')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/FileDumperTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/FileDumperTest.php new file mode 100644 index 0000000..6e42b1e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/FileDumperTest.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\FileDumper; +use Symfony\Component\Translation\MessageCatalogue; + +class FileDumperTest extends TestCase +{ + public function testDump() + { + $tempDir = sys_get_temp_dir(); + + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => 'bar']); + + $dumper = new ConcreteFileDumper(); + $dumper->dump($catalogue, ['path' => $tempDir]); + + $this->assertFileExists($tempDir.'/messages.en.concrete'); + + @unlink($tempDir.'/messages.en.concrete'); + } + + public function testDumpIntl() + { + $tempDir = sys_get_temp_dir(); + + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => 'bar'], 'd1'); + $catalogue->add(['bar' => 'foo'], 'd1+intl-icu'); + $catalogue->add(['bar' => 'foo'], 'd2+intl-icu'); + + $dumper = new ConcreteFileDumper(); + @unlink($tempDir.'/d2.en.concrete'); + $dumper->dump($catalogue, ['path' => $tempDir]); + + $this->assertStringEqualsFile($tempDir.'/d1.en.concrete', 'foo=bar'); + @unlink($tempDir.'/d1.en.concrete'); + + $this->assertStringEqualsFile($tempDir.'/d1+intl-icu.en.concrete', 'bar=foo'); + @unlink($tempDir.'/d1+intl-icu.en.concrete'); + + $this->assertFileNotExists($tempDir.'/d2.en.concrete'); + $this->assertStringEqualsFile($tempDir.'/d2+intl-icu.en.concrete', 'bar=foo'); + @unlink($tempDir.'/d2+intl-icu.en.concrete'); + } + + public function testDumpCreatesNestedDirectoriesAndFile() + { + $tempDir = sys_get_temp_dir(); + $translationsDir = $tempDir.'/test/translations'; + $file = $translationsDir.'/messages.en.concrete'; + + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => 'bar']); + + $dumper = new ConcreteFileDumper(); + $dumper->setRelativePathTemplate('test/translations/%domain%.%locale%.%extension%'); + $dumper->dump($catalogue, ['path' => $tempDir]); + + $this->assertFileExists($file); + + @unlink($file); + @rmdir($translationsDir); + } +} + +class ConcreteFileDumper extends FileDumper +{ + public function formatCatalogue(MessageCatalogue $messages, $domain, array $options = []): string + { + return http_build_query($messages->all($domain), '', '&'); + } + + protected function getExtension(): string + { + return 'concrete'; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/IcuResFileDumperTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/IcuResFileDumperTest.php new file mode 100644 index 0000000..dcb9c2c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/IcuResFileDumperTest.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\IcuResFileDumper; +use Symfony\Component\Translation\MessageCatalogue; + +class IcuResFileDumperTest extends TestCase +{ + public function testFormatCatalogue() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => 'bar']); + + $dumper = new IcuResFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/resourcebundle/res/en.res', $dumper->formatCatalogue($catalogue, 'messages')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/IniFileDumperTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/IniFileDumperTest.php new file mode 100644 index 0000000..1ed168b --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/IniFileDumperTest.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\IniFileDumper; +use Symfony\Component\Translation\MessageCatalogue; + +class IniFileDumperTest extends TestCase +{ + public function testFormatCatalogue() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => 'bar']); + + $dumper = new IniFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.ini', $dumper->formatCatalogue($catalogue, 'messages')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/JsonFileDumperTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/JsonFileDumperTest.php new file mode 100644 index 0000000..04e3d86 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/JsonFileDumperTest.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\JsonFileDumper; +use Symfony\Component\Translation\MessageCatalogue; + +class JsonFileDumperTest extends TestCase +{ + public function testFormatCatalogue() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => 'bar']); + + $dumper = new JsonFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.json', $dumper->formatCatalogue($catalogue, 'messages')); + } + + public function testDumpWithCustomEncoding() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => '"bar"']); + + $dumper = new JsonFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.dump.json', $dumper->formatCatalogue($catalogue, 'messages', ['json_encoding' => JSON_HEX_QUOT])); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/MoFileDumperTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/MoFileDumperTest.php new file mode 100644 index 0000000..fbbd75d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/MoFileDumperTest.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\MoFileDumper; +use Symfony\Component\Translation\MessageCatalogue; + +class MoFileDumperTest extends TestCase +{ + public function testFormatCatalogue() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => 'bar']); + + $dumper = new MoFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.mo', $dumper->formatCatalogue($catalogue, 'messages')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/PhpFileDumperTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/PhpFileDumperTest.php new file mode 100644 index 0000000..00e535d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/PhpFileDumperTest.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\PhpFileDumper; +use Symfony\Component\Translation\MessageCatalogue; + +class PhpFileDumperTest extends TestCase +{ + public function testFormatCatalogue() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => 'bar']); + + $dumper = new PhpFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.php', $dumper->formatCatalogue($catalogue, 'messages')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/PoFileDumperTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/PoFileDumperTest.php new file mode 100644 index 0000000..81f35f2 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/PoFileDumperTest.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\PoFileDumper; +use Symfony\Component\Translation\MessageCatalogue; + +class PoFileDumperTest extends TestCase +{ + public function testFormatCatalogue() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => 'bar', 'bar' => 'foo', 'foo_bar' => 'foobar', 'bar_foo' => 'barfoo']); + $catalogue->setMetadata('foo_bar', [ + 'comments' => [ + 'Comment 1', + 'Comment 2', + ], + 'flags' => [ + 'fuzzy', + 'another', + ], + 'sources' => [ + 'src/file_1', + 'src/file_2:50', + ], + ]); + $catalogue->setMetadata('bar_foo', [ + 'comments' => 'Comment', + 'flags' => 'fuzzy', + 'sources' => 'src/file_1', + ]); + + $dumper = new PoFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.po', $dumper->formatCatalogue($catalogue, 'messages')); + } + + public function testDumpPlurals() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add([ + 'foo|foos' => 'bar|bars', + '{0} no foos|one foo|%count% foos' => '{0} no bars|one bar|%count% bars', + ]); + + $dumper = new PoFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/plurals.po', $dumper->formatCatalogue($catalogue, 'messages')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/QtFileDumperTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/QtFileDumperTest.php new file mode 100644 index 0000000..6c4b559 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/QtFileDumperTest.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\QtFileDumper; +use Symfony\Component\Translation\MessageCatalogue; + +class QtFileDumperTest extends TestCase +{ + public function testFormatCatalogue() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add(['foo' => 'bar', 'foo_bar' => 'foobar', 'bar_foo' => 'barfoo'], 'resources'); + $catalogue->setMetadata('foo_bar', [ + 'comments' => [ + 'Comment 1', + 'Comment 2', + ], + 'flags' => [ + 'fuzzy', + 'another', + ], + 'sources' => [ + 'src/file_1', + 'src/file_2:50', + ], + ], 'resources'); + $catalogue->setMetadata('bar_foo', [ + 'comments' => 'Comment', + 'flags' => 'fuzzy', + 'sources' => 'src/file_1', + ], 'resources'); + + $dumper = new QtFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.ts', $dumper->formatCatalogue($catalogue, 'resources')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/XliffFileDumperTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/XliffFileDumperTest.php new file mode 100644 index 0000000..6377132 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/XliffFileDumperTest.php @@ -0,0 +1,130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\XliffFileDumper; +use Symfony\Component\Translation\MessageCatalogue; + +class XliffFileDumperTest extends TestCase +{ + public function testFormatCatalogue() + { + $catalogue = new MessageCatalogue('en_US'); + $catalogue->add([ + 'foo' => 'bar', + 'key' => '', + 'key.with.cdata' => ' & ', + ]); + $catalogue->setMetadata('foo', ['notes' => [['priority' => 1, 'from' => 'bar', 'content' => 'baz']]]); + $catalogue->setMetadata('key', ['notes' => [['content' => 'baz'], ['content' => 'qux']]]); + + $dumper = new XliffFileDumper(); + + $this->assertStringEqualsFile( + __DIR__.'/../fixtures/resources-clean.xlf', + $dumper->formatCatalogue($catalogue, 'messages', ['default_locale' => 'fr_FR']) + ); + } + + public function testFormatCatalogueXliff2() + { + $catalogue = new MessageCatalogue('en_US'); + $catalogue->add([ + 'foo' => 'bar', + 'key' => '', + 'key.with.cdata' => ' & ', + ]); + $catalogue->setMetadata('key', ['target-attributes' => ['order' => 1]]); + + $dumper = new XliffFileDumper(); + + $this->assertStringEqualsFile( + __DIR__.'/../fixtures/resources-2.0-clean.xlf', + $dumper->formatCatalogue($catalogue, 'messages', ['default_locale' => 'fr_FR', 'xliff_version' => '2.0']) + ); + } + + public function testFormatIcuCatalogueXliff2() + { + $catalogue = new MessageCatalogue('en_US'); + $catalogue->add([ + 'foo' => 'bar', + ], 'messages'.MessageCatalogue::INTL_DOMAIN_SUFFIX); + + $dumper = new XliffFileDumper(); + + $this->assertStringEqualsFile( + __DIR__.'/../fixtures/resources-2.0+intl-icu.xlf', + $dumper->formatCatalogue($catalogue, 'messages'.MessageCatalogue::INTL_DOMAIN_SUFFIX, ['default_locale' => 'fr_FR', 'xliff_version' => '2.0']) + ); + } + + public function testFormatCatalogueWithCustomToolInfo() + { + $options = [ + 'default_locale' => 'en_US', + 'tool_info' => ['tool-id' => 'foo', 'tool-name' => 'foo', 'tool-version' => '0.0', 'tool-company' => 'Foo'], + ]; + + $catalogue = new MessageCatalogue('en_US'); + $catalogue->add(['foo' => 'bar']); + + $dumper = new XliffFileDumper(); + + $this->assertStringEqualsFile( + __DIR__.'/../fixtures/resources-tool-info.xlf', + $dumper->formatCatalogue($catalogue, 'messages', $options) + ); + } + + public function testFormatCatalogueWithTargetAttributesMetadata() + { + $catalogue = new MessageCatalogue('en_US'); + $catalogue->add([ + 'foo' => 'bar', + ]); + $catalogue->setMetadata('foo', ['target-attributes' => ['state' => 'needs-translation']]); + + $dumper = new XliffFileDumper(); + + $this->assertStringEqualsFile( + __DIR__.'/../fixtures/resources-target-attributes.xlf', + $dumper->formatCatalogue($catalogue, 'messages', ['default_locale' => 'fr_FR']) + ); + } + + public function testFormatCatalogueWithNotesMetadata() + { + $catalogue = new MessageCatalogue('en_US'); + $catalogue->add([ + 'foo' => 'bar', + 'baz' => 'biz', + ]); + $catalogue->setMetadata('foo', ['notes' => [ + ['category' => 'state', 'content' => 'new'], + ['category' => 'approved', 'content' => 'true'], + ['category' => 'section', 'content' => 'user login', 'priority' => '1'], + ]]); + $catalogue->setMetadata('baz', ['notes' => [ + ['id' => 'x', 'content' => 'x_content'], + ['appliesTo' => 'target', 'category' => 'quality', 'content' => 'Fuzzy'], + ]]); + + $dumper = new XliffFileDumper(); + + $this->assertStringEqualsFile( + __DIR__.'/../fixtures/resources-notes-meta.xlf', + $dumper->formatCatalogue($catalogue, 'messages', ['default_locale' => 'fr_FR', 'xliff_version' => '2.0']) + ); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/YamlFileDumperTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/YamlFileDumperTest.php new file mode 100644 index 0000000..e46da5a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Dumper/YamlFileDumperTest.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\YamlFileDumper; +use Symfony\Component\Translation\MessageCatalogue; + +class YamlFileDumperTest extends TestCase +{ + public function testTreeFormatCatalogue() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add([ + 'foo.bar1' => 'value1', + 'foo.bar2' => 'value2', + ]); + + $dumper = new YamlFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/messages.yml', $dumper->formatCatalogue($catalogue, 'messages', ['as_tree' => true, 'inline' => 999])); + } + + public function testLinearFormatCatalogue() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add([ + 'foo.bar1' => 'value1', + 'foo.bar2' => 'value2', + ]); + + $dumper = new YamlFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/messages_linear.yml', $dumper->formatCatalogue($catalogue, 'messages')); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Extractor/PhpExtractorTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Extractor/PhpExtractorTest.php new file mode 100644 index 0000000..a6d7c50 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Extractor/PhpExtractorTest.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Extractor; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Extractor\PhpExtractor; +use Symfony\Component\Translation\MessageCatalogue; + +class PhpExtractorTest extends TestCase +{ + /** + * @dataProvider resourcesProvider + * + * @param array|string $resource + */ + public function testExtraction($resource) + { + // Arrange + $extractor = new PhpExtractor(); + $extractor->setPrefix('prefix'); + $catalogue = new MessageCatalogue('en'); + + // Act + $extractor->extract($resource, $catalogue); + + $expectedHeredoc = << [ + 'single-quoted key' => 'prefixsingle-quoted key', + 'double-quoted key' => 'prefixdouble-quoted key', + 'heredoc key' => 'prefixheredoc key', + 'nowdoc key' => 'prefixnowdoc key', + "double-quoted key with whitespace and escaped \$\n\" sequences" => "prefixdouble-quoted key with whitespace and escaped \$\n\" sequences", + 'single-quoted key with whitespace and nonescaped \$\n\' sequences' => 'prefixsingle-quoted key with whitespace and nonescaped \$\n\' sequences', + 'single-quoted key with "quote mark at the end"' => 'prefixsingle-quoted key with "quote mark at the end"', + $expectedHeredoc => 'prefix'.$expectedHeredoc, + $expectedNowdoc => 'prefix'.$expectedNowdoc, + '{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples' => 'prefix{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples', + 'concatenated message with heredoc and nowdoc' => 'prefixconcatenated message with heredoc and nowdoc', + 'default domain' => 'prefixdefault domain', + ], + 'not_messages' => [ + 'other-domain-test-no-params-short-array' => 'prefixother-domain-test-no-params-short-array', + 'other-domain-test-no-params-long-array' => 'prefixother-domain-test-no-params-long-array', + 'other-domain-test-params-short-array' => 'prefixother-domain-test-params-short-array', + 'other-domain-test-params-long-array' => 'prefixother-domain-test-params-long-array', + 'other-domain-test-trans-choice-short-array-%count%' => 'prefixother-domain-test-trans-choice-short-array-%count%', + 'other-domain-test-trans-choice-long-array-%count%' => 'prefixother-domain-test-trans-choice-long-array-%count%', + 'typecast' => 'prefixtypecast', + 'msg1' => 'prefixmsg1', + 'msg2' => 'prefixmsg2', + ], + ]; + $actualCatalogue = $catalogue->all(); + + $this->assertEquals($expectedCatalogue, $actualCatalogue); + + $filename = str_replace(\DIRECTORY_SEPARATOR, '/', __DIR__).'/../fixtures/extractor/translation.html.php'; + $this->assertEquals(['sources' => [$filename.':2']], $catalogue->getMetadata('single-quoted key')); + $this->assertEquals(['sources' => [$filename.':43']], $catalogue->getMetadata('other-domain-test-no-params-short-array', 'not_messages')); + } + + public function resourcesProvider() + { + $directory = __DIR__.'/../fixtures/extractor/'; + $splFiles = []; + foreach (new \DirectoryIterator($directory) as $fileInfo) { + if ($fileInfo->isDot()) { + continue; + } + if ('translation.html.php' === $fileInfo->getBasename()) { + $phpFile = $fileInfo->getPathname(); + } + $splFiles[] = $fileInfo->getFileInfo(); + } + + return [ + [$directory], + [$phpFile], + [glob($directory.'*')], + [$splFiles], + [new \ArrayObject(glob($directory.'*'))], + [new \ArrayObject($splFiles)], + ]; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Formatter/IntlFormatterTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Formatter/IntlFormatterTest.php new file mode 100644 index 0000000..37d982c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Formatter/IntlFormatterTest.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Formatter; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Formatter\IntlFormatter; +use Symfony\Component\Translation\Formatter\IntlFormatterInterface; + +/** + * @requires extension intl + */ +class IntlFormatterTest extends \PHPUnit\Framework\TestCase +{ + /** + * @dataProvider provideDataForFormat + */ + public function testFormat($expected, $message, $arguments) + { + $this->assertEquals($expected, trim((new IntlFormatter())->formatIntl($message, 'en', $arguments))); + } + + public function testInvalidFormat() + { + $this->expectException(InvalidArgumentException::class); + (new IntlFormatter())->formatIntl('{foo', 'en', [2]); + } + + public function testFormatWithNamedArguments() + { + if (version_compare(INTL_ICU_VERSION, '4.8', '<')) { + $this->markTestSkipped('Format with named arguments can only be run with ICU 4.8 or higher and PHP >= 5.5'); + } + + $chooseMessage = <<<'_MSG_' +{gender_of_host, select, + female {{num_guests, plural, offset:1 + =0 {{host} does not give a party.} + =1 {{host} invites {guest} to her party.} + =2 {{host} invites {guest} and one other person to her party.} + other {{host} invites {guest} as one of the # people invited to her party.}}} + male {{num_guests, plural, offset:1 + =0 {{host} does not give a party.} + =1 {{host} invites {guest} to his party.} + =2 {{host} invites {guest} and one other person to his party.} + other {{host} invites {guest} as one of the # people invited to his party.}}} + other {{num_guests, plural, offset:1 + =0 {{host} does not give a party.} + =1 {{host} invites {guest} to their party.} + =2 {{host} invites {guest} and one other person to their party.} + other {{host} invites {guest} as one of the # people invited to their party.}}}} +_MSG_; + + $message = (new IntlFormatter())->formatIntl($chooseMessage, 'en', [ + 'gender_of_host' => 'male', + 'num_guests' => 10, + 'host' => 'Fabien', + 'guest' => 'Guilherme', + ]); + + $this->assertEquals('Fabien invites Guilherme as one of the 9 people invited to his party.', $message); + } + + public function provideDataForFormat() + { + return [ + [ + 'There is one apple', + 'There is one apple', + [], + ], + [ + '4,560 monkeys on 123 trees make 37.073 monkeys per tree', + '{0,number,integer} monkeys on {1,number,integer} trees make {2,number} monkeys per tree', + [4560, 123, 4560 / 123], + ], + [ + '', + '', + [], + ], + ]; + } + + public function testPercentsAndBracketsAreTrimmed() + { + $formatter = new IntlFormatter(); + $this->assertInstanceof(IntlFormatterInterface::class, $formatter); + $this->assertSame('Hello Fab', $formatter->formatIntl('Hello {name}', 'en', ['name' => 'Fab'])); + $this->assertSame('Hello Fab', $formatter->formatIntl('Hello {name}', 'en', ['%name%' => 'Fab'])); + $this->assertSame('Hello Fab', $formatter->formatIntl('Hello {name}', 'en', ['{{ name }}' => 'Fab'])); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Formatter/MessageFormatterTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Formatter/MessageFormatterTest.php new file mode 100644 index 0000000..232bcf9 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Formatter/MessageFormatterTest.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Formatter; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Formatter\MessageFormatter; + +class MessageFormatterTest extends TestCase +{ + /** + * @dataProvider getTransMessages + */ + public function testFormat($expected, $message, $parameters = []) + { + $this->assertEquals($expected, $this->getMessageFormatter()->format($message, 'en', $parameters)); + } + + /** + * @dataProvider getTransChoiceMessages + * @group legacy + */ + public function testFormatPlural($expected, $message, $number, $parameters) + { + $this->assertEquals($expected, $this->getMessageFormatter()->choiceFormat($message, $number, 'fr', $parameters)); + } + + public function getTransMessages() + { + return [ + [ + 'There is one apple', + 'There is one apple', + ], + [ + 'There are 5 apples', + 'There are %count% apples', + ['%count%' => 5], + ], + [ + 'There are 5 apples', + 'There are {{count}} apples', + ['{{count}}' => 5], + ], + ]; + } + + public function getTransChoiceMessages() + { + return [ + ['Il y a 0 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, ['%count%' => 0]], + ['Il y a 1 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 1, ['%count%' => 1]], + ['Il y a 10 pommes', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 10, ['%count%' => 10]], + + ['Il y a 0 pomme', 'Il y a %count% pomme|Il y a %count% pommes', 0, ['%count%' => 0]], + ['Il y a 1 pomme', 'Il y a %count% pomme|Il y a %count% pommes', 1, ['%count%' => 1]], + ['Il y a 10 pommes', 'Il y a %count% pomme|Il y a %count% pommes', 10, ['%count%' => 10]], + + ['Il y a 0 pomme', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 0, ['%count%' => 0]], + ['Il y a 1 pomme', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 1, ['%count%' => 1]], + ['Il y a 10 pommes', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 10, ['%count%' => 10]], + + ['Il n\'y a aucune pomme', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 0, ['%count%' => 0]], + ['Il y a 1 pomme', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 1, ['%count%' => 1]], + ['Il y a 10 pommes', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 10, ['%count%' => 10]], + + ['Il y a 0 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, ['%count%' => 0]], + ]; + } + + private function getMessageFormatter() + { + return new MessageFormatter(); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/IdentityTranslatorTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/IdentityTranslatorTest.php new file mode 100644 index 0000000..a630a7a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/IdentityTranslatorTest.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests; + +use Symfony\Component\Translation\IdentityTranslator; +use Symfony\Contracts\Translation\Test\TranslatorTest; + +class IdentityTranslatorTest extends TranslatorTest +{ + private $defaultLocale; + + protected function setUp(): void + { + parent::setUp(); + + $this->defaultLocale = \Locale::getDefault(); + } + + protected function tearDown(): void + { + parent::tearDown(); + + \Locale::setDefault($this->defaultLocale); + } + + public function getTranslator() + { + return new IdentityTranslator(); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/IntervalTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/IntervalTest.php new file mode 100644 index 0000000..ea3e4d8 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/IntervalTest.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Interval; + +/** + * @group legacy + */ +class IntervalTest extends TestCase +{ + /** + * @dataProvider getTests + */ + public function testTest($expected, $number, $interval) + { + $this->assertEquals($expected, Interval::test($number, $interval)); + } + + public function testTestException() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidArgumentException'); + Interval::test(1, 'foobar'); + } + + public function getTests() + { + return [ + [true, 3, '{1,2, 3 ,4}'], + [false, 10, '{1,2, 3 ,4}'], + [false, 3, '[1,2]'], + [true, 1, '[1,2]'], + [true, 2, '[1,2]'], + [false, 1, ']1,2['], + [false, 2, ']1,2['], + [true, log(0), '[-Inf,2['], + [true, -log(0), '[-2,+Inf]'], + ]; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/CsvFileLoaderTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/CsvFileLoaderTest.php new file mode 100644 index 0000000..9537e1f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/CsvFileLoaderTest.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Loader\CsvFileLoader; + +class CsvFileLoaderTest extends TestCase +{ + public function testLoad() + { + $loader = new CsvFileLoader(); + $resource = __DIR__.'/../fixtures/resources.csv'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals(['foo' => 'bar'], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadDoesNothingIfEmpty() + { + $loader = new CsvFileLoader(); + $resource = __DIR__.'/../fixtures/empty.csv'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals([], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadNonExistingResource() + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loader = new CsvFileLoader(); + $resource = __DIR__.'/../fixtures/not-exists.csv'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadNonLocalResource() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new CsvFileLoader(); + $resource = 'http://example.com/resources.csv'; + $loader->load($resource, 'en', 'domain1'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/IcuDatFileLoaderTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/IcuDatFileLoaderTest.php new file mode 100644 index 0000000..77db041 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/IcuDatFileLoaderTest.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Loader\IcuDatFileLoader; + +/** + * @requires extension intl + */ +class IcuDatFileLoaderTest extends LocalizedTestCase +{ + public function testLoadInvalidResource() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new IcuDatFileLoader(); + $loader->load(__DIR__.'/../fixtures/resourcebundle/corrupted/resources', 'es', 'domain2'); + } + + public function testDatEnglishLoad() + { + // bundled resource is build using pkgdata command which at least in ICU 4.2 comes in extremely! buggy form + // you must specify an temporary build directory which is not the same as current directory and + // MUST reside on the same partition. pkgdata -p resources -T /srv -d.packagelist.txt + $loader = new IcuDatFileLoader(); + $resource = __DIR__.'/../fixtures/resourcebundle/dat/resources'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals(['symfony' => 'Symfony 2 is great'], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource.'.dat')], $catalogue->getResources()); + } + + public function testDatFrenchLoad() + { + $loader = new IcuDatFileLoader(); + $resource = __DIR__.'/../fixtures/resourcebundle/dat/resources'; + $catalogue = $loader->load($resource, 'fr', 'domain1'); + + $this->assertEquals(['symfony' => 'Symfony 2 est génial'], $catalogue->all('domain1')); + $this->assertEquals('fr', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource.'.dat')], $catalogue->getResources()); + } + + public function testLoadNonExistingResource() + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loader = new IcuDatFileLoader(); + $loader->load(__DIR__.'/../fixtures/non-existing.txt', 'en', 'domain1'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/IcuResFileLoaderTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/IcuResFileLoaderTest.php new file mode 100644 index 0000000..99b2f90 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/IcuResFileLoaderTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use Symfony\Component\Config\Resource\DirectoryResource; +use Symfony\Component\Translation\Loader\IcuResFileLoader; + +/** + * @requires extension intl + */ +class IcuResFileLoaderTest extends LocalizedTestCase +{ + public function testLoad() + { + // resource is build using genrb command + $loader = new IcuResFileLoader(); + $resource = __DIR__.'/../fixtures/resourcebundle/res'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals(['foo' => 'bar'], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new DirectoryResource($resource)], $catalogue->getResources()); + } + + public function testLoadNonExistingResource() + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loader = new IcuResFileLoader(); + $loader->load(__DIR__.'/../fixtures/non-existing.txt', 'en', 'domain1'); + } + + public function testLoadInvalidResource() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new IcuResFileLoader(); + $loader->load(__DIR__.'/../fixtures/resourcebundle/corrupted', 'en', 'domain1'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/IniFileLoaderTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/IniFileLoaderTest.php new file mode 100644 index 0000000..fd66e20 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/IniFileLoaderTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Loader\IniFileLoader; + +class IniFileLoaderTest extends TestCase +{ + public function testLoad() + { + $loader = new IniFileLoader(); + $resource = __DIR__.'/../fixtures/resources.ini'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals(['foo' => 'bar'], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadDoesNothingIfEmpty() + { + $loader = new IniFileLoader(); + $resource = __DIR__.'/../fixtures/empty.ini'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals([], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadNonExistingResource() + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loader = new IniFileLoader(); + $resource = __DIR__.'/../fixtures/non-existing.ini'; + $loader->load($resource, 'en', 'domain1'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/JsonFileLoaderTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/JsonFileLoaderTest.php new file mode 100644 index 0000000..c5a9ca6 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/JsonFileLoaderTest.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Loader\JsonFileLoader; + +class JsonFileLoaderTest extends TestCase +{ + public function testLoad() + { + $loader = new JsonFileLoader(); + $resource = __DIR__.'/../fixtures/resources.json'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals(['foo' => 'bar'], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadDoesNothingIfEmpty() + { + $loader = new JsonFileLoader(); + $resource = __DIR__.'/../fixtures/empty.json'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals([], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadNonExistingResource() + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loader = new JsonFileLoader(); + $resource = __DIR__.'/../fixtures/non-existing.json'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testParseException() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $this->expectExceptionMessage('Error parsing JSON: Syntax error, malformed JSON'); + $loader = new JsonFileLoader(); + $resource = __DIR__.'/../fixtures/malformed.json'; + $loader->load($resource, 'en', 'domain1'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/LocalizedTestCase.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/LocalizedTestCase.php new file mode 100644 index 0000000..b4a4a12 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/LocalizedTestCase.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use PHPUnit\Framework\TestCase; + +abstract class LocalizedTestCase extends TestCase +{ + protected function setUp(): void + { + if (!\extension_loaded('intl')) { + $this->markTestSkipped('Extension intl is required.'); + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/MoFileLoaderTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/MoFileLoaderTest.php new file mode 100644 index 0000000..3fe3a99 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/MoFileLoaderTest.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Loader\MoFileLoader; + +class MoFileLoaderTest extends TestCase +{ + public function testLoad() + { + $loader = new MoFileLoader(); + $resource = __DIR__.'/../fixtures/resources.mo'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals(['foo' => 'bar'], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadPlurals() + { + $loader = new MoFileLoader(); + $resource = __DIR__.'/../fixtures/plurals.mo'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals([ + 'foo|foos' => 'bar|bars', + '{0} no foos|one foo|%count% foos' => '{0} no bars|one bar|%count% bars', + ], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadNonExistingResource() + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loader = new MoFileLoader(); + $resource = __DIR__.'/../fixtures/non-existing.mo'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadInvalidResource() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new MoFileLoader(); + $resource = __DIR__.'/../fixtures/empty.mo'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadEmptyTranslation() + { + $loader = new MoFileLoader(); + $resource = __DIR__.'/../fixtures/empty-translation.mo'; + $catalogue = $loader->load($resource, 'en', 'message'); + + $this->assertEquals([], $catalogue->all('message')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/PhpFileLoaderTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/PhpFileLoaderTest.php new file mode 100644 index 0000000..d4da645 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/PhpFileLoaderTest.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Loader\PhpFileLoader; + +class PhpFileLoaderTest extends TestCase +{ + public function testLoad() + { + $loader = new PhpFileLoader(); + $resource = __DIR__.'/../fixtures/resources.php'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals(['foo' => 'bar'], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadNonExistingResource() + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loader = new PhpFileLoader(); + $resource = __DIR__.'/../fixtures/non-existing.php'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadThrowsAnExceptionIfFileNotLocal() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new PhpFileLoader(); + $resource = 'http://example.com/resources.php'; + $loader->load($resource, 'en', 'domain1'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/PoFileLoaderTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/PoFileLoaderTest.php new file mode 100644 index 0000000..72c4c66 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/PoFileLoaderTest.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Loader\PoFileLoader; + +class PoFileLoaderTest extends TestCase +{ + public function testLoad() + { + $loader = new PoFileLoader(); + $resource = __DIR__.'/../fixtures/resources.po'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals(['foo' => 'bar', 'bar' => 'foo'], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadPlurals() + { + $loader = new PoFileLoader(); + $resource = __DIR__.'/../fixtures/plurals.po'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals([ + 'foo|foos' => 'bar|bars', + '{0} no foos|one foo|%count% foos' => '{0} no bars|one bar|%count% bars', + ], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadDoesNothingIfEmpty() + { + $loader = new PoFileLoader(); + $resource = __DIR__.'/../fixtures/empty.po'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals([], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadNonExistingResource() + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loader = new PoFileLoader(); + $resource = __DIR__.'/../fixtures/non-existing.po'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadEmptyTranslation() + { + $loader = new PoFileLoader(); + $resource = __DIR__.'/../fixtures/empty-translation.po'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals(['foo' => ''], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testEscapedId() + { + $loader = new PoFileLoader(); + $resource = __DIR__.'/../fixtures/escaped-id.po'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $messages = $catalogue->all('domain1'); + $this->assertArrayHasKey('escaped "foo"', $messages); + $this->assertEquals('escaped "bar"', $messages['escaped "foo"']); + } + + public function testEscapedIdPlurals() + { + $loader = new PoFileLoader(); + $resource = __DIR__.'/../fixtures/escaped-id-plurals.po'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $messages = $catalogue->all('domain1'); + $this->assertArrayHasKey('escaped "foo"|escaped "foos"', $messages); + $this->assertEquals('escaped "bar"|escaped "bars"', $messages['escaped "foo"|escaped "foos"']); + } + + public function testSkipFuzzyTranslations() + { + $loader = new PoFileLoader(); + $resource = __DIR__.'/../fixtures/fuzzy-translations.po'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $messages = $catalogue->all('domain1'); + $this->assertArrayHasKey('foo1', $messages); + $this->assertArrayNotHasKey('foo2', $messages); + $this->assertArrayHasKey('foo3', $messages); + } + + public function testMissingPlurals() + { + $loader = new PoFileLoader(); + $resource = __DIR__.'/../fixtures/missing-plurals.po'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals([ + 'foo|foos' => '-|bar|-|bars', + ], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/QtFileLoaderTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/QtFileLoaderTest.php new file mode 100644 index 0000000..95981c7 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/QtFileLoaderTest.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Loader\QtFileLoader; + +class QtFileLoaderTest extends TestCase +{ + public function testLoad() + { + $loader = new QtFileLoader(); + $resource = __DIR__.'/../fixtures/resources.ts'; + $catalogue = $loader->load($resource, 'en', 'resources'); + + $this->assertEquals([ + 'foo' => 'bar', + 'foo_bar' => 'foobar', + 'bar_foo' => 'barfoo', + ], $catalogue->all('resources')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadNonExistingResource() + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loader = new QtFileLoader(); + $resource = __DIR__.'/../fixtures/non-existing.ts'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadNonLocalResource() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new QtFileLoader(); + $resource = 'http://domain1.com/resources.ts'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadInvalidResource() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new QtFileLoader(); + $resource = __DIR__.'/../fixtures/invalid-xml-resources.xlf'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadEmptyResource() + { + $loader = new QtFileLoader(); + $resource = __DIR__.'/../fixtures/empty.xlf'; + + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $this->expectExceptionMessage(sprintf('Unable to load "%s".', $resource)); + + $loader->load($resource, 'en', 'domain1'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/XliffFileLoaderTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/XliffFileLoaderTest.php new file mode 100644 index 0000000..79e51f1 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/XliffFileLoaderTest.php @@ -0,0 +1,317 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Loader\XliffFileLoader; + +class XliffFileLoaderTest extends TestCase +{ + public function testLoad() + { + $loader = new XliffFileLoader(); + $resource = __DIR__.'/../fixtures/resources.xlf'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + $this->assertSame([], libxml_get_errors()); + $this->assertContainsOnly('string', $catalogue->all('domain1')); + } + + public function testLoadWithInternalErrorsEnabled() + { + $internalErrors = libxml_use_internal_errors(true); + + $this->assertSame([], libxml_get_errors()); + + $loader = new XliffFileLoader(); + $resource = __DIR__.'/../fixtures/resources.xlf'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + $this->assertSame([], libxml_get_errors()); + + libxml_clear_errors(); + libxml_use_internal_errors($internalErrors); + } + + public function testLoadWithExternalEntitiesDisabled() + { + $disableEntities = libxml_disable_entity_loader(true); + + $loader = new XliffFileLoader(); + $resource = __DIR__.'/../fixtures/resources.xlf'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + libxml_disable_entity_loader($disableEntities); + + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadWithResname() + { + $loader = new XliffFileLoader(); + $catalogue = $loader->load(__DIR__.'/../fixtures/resname.xlf', 'en', 'domain1'); + + $this->assertEquals(['foo' => 'bar', 'bar' => 'baz', 'baz' => 'foo', 'qux' => 'qux source'], $catalogue->all('domain1')); + } + + public function testIncompleteResource() + { + $loader = new XliffFileLoader(); + $catalogue = $loader->load(__DIR__.'/../fixtures/resources.xlf', 'en', 'domain1'); + + $this->assertEquals(['foo' => 'bar', 'extra' => 'extra', 'key' => '', 'test' => 'with'], $catalogue->all('domain1')); + } + + public function testEncoding() + { + $loader = new XliffFileLoader(); + $catalogue = $loader->load(__DIR__.'/../fixtures/encoding.xlf', 'en', 'domain1'); + + $this->assertEquals(utf8_decode('föö'), $catalogue->get('bar', 'domain1')); + $this->assertEquals(utf8_decode('bär'), $catalogue->get('foo', 'domain1')); + $this->assertEquals( + [ + 'source' => 'foo', + 'notes' => [['content' => utf8_decode('bäz')]], + 'id' => '1', + 'file' => [ + 'original' => 'file.ext', + ], + ], + $catalogue->getMetadata('foo', 'domain1') + ); + } + + public function testTargetAttributesAreStoredCorrectly() + { + $loader = new XliffFileLoader(); + $catalogue = $loader->load(__DIR__.'/../fixtures/with-attributes.xlf', 'en', 'domain1'); + + $metadata = $catalogue->getMetadata('foo', 'domain1'); + $this->assertEquals('translated', $metadata['target-attributes']['state']); + } + + public function testLoadInvalidResource() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new XliffFileLoader(); + $loader->load(__DIR__.'/../fixtures/resources.php', 'en', 'domain1'); + } + + public function testLoadResourceDoesNotValidate() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new XliffFileLoader(); + $loader->load(__DIR__.'/../fixtures/non-valid.xlf', 'en', 'domain1'); + } + + public function testLoadNonExistingResource() + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loader = new XliffFileLoader(); + $resource = __DIR__.'/../fixtures/non-existing.xlf'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadThrowsAnExceptionIfFileNotLocal() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new XliffFileLoader(); + $resource = 'http://example.com/resources.xlf'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testDocTypeIsNotAllowed() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $this->expectExceptionMessage('Document types are not allowed.'); + $loader = new XliffFileLoader(); + $loader->load(__DIR__.'/../fixtures/withdoctype.xlf', 'en', 'domain1'); + } + + public function testParseEmptyFile() + { + $loader = new XliffFileLoader(); + $resource = __DIR__.'/../fixtures/empty.xlf'; + + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $this->expectExceptionMessage(sprintf('Unable to load "%s":', $resource)); + + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadNotes() + { + $loader = new XliffFileLoader(); + $catalogue = $loader->load(__DIR__.'/../fixtures/withnote.xlf', 'en', 'domain1'); + + $this->assertEquals( + [ + 'source' => 'foo', + 'notes' => [['priority' => 1, 'content' => 'foo']], + 'id' => '1', + 'file' => [ + 'original' => 'file.ext', + ], + ], + $catalogue->getMetadata('foo', 'domain1') + ); + // message without target + $this->assertEquals( + [ + 'source' => 'extrasource', + 'notes' => [['content' => 'bar', 'from' => 'foo']], + 'id' => '2', + 'file' => [ + 'original' => 'file.ext', + ], + ], + $catalogue->getMetadata('extra', 'domain1') + ); + // message with empty target + $this->assertEquals( + [ + 'source' => 'key', + 'notes' => [ + ['content' => 'baz'], + ['priority' => 2, 'from' => 'bar', 'content' => 'qux'], + ], + 'id' => '123', + 'file' => [ + 'original' => 'file.ext', + ], + ], + $catalogue->getMetadata('key', 'domain1') + ); + } + + public function testLoadVersion2() + { + $loader = new XliffFileLoader(); + $resource = __DIR__.'/../fixtures/resources-2.0.xlf'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + $this->assertSame([], libxml_get_errors()); + + $domains = $catalogue->all(); + $this->assertCount(3, $domains['domain1']); + $this->assertContainsOnly('string', $catalogue->all('domain1')); + + // target attributes + $this->assertEquals(['target-attributes' => ['order' => 1]], $catalogue->getMetadata('bar', 'domain1')); + } + + public function testLoadVersion2WithNoteMeta() + { + $loader = new XliffFileLoader(); + $resource = __DIR__.'/../fixtures/resources-notes-meta.xlf'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + $this->assertSame([], libxml_get_errors()); + + // test for "foo" metadata + $this->assertTrue($catalogue->defines('foo', 'domain1')); + $metadata = $catalogue->getMetadata('foo', 'domain1'); + $this->assertNotEmpty($metadata); + $this->assertCount(3, $metadata['notes']); + + $this->assertEquals('state', $metadata['notes'][0]['category']); + $this->assertEquals('new', $metadata['notes'][0]['content']); + + $this->assertEquals('approved', $metadata['notes'][1]['category']); + $this->assertEquals('true', $metadata['notes'][1]['content']); + + $this->assertEquals('section', $metadata['notes'][2]['category']); + $this->assertEquals('1', $metadata['notes'][2]['priority']); + $this->assertEquals('user login', $metadata['notes'][2]['content']); + + // test for "baz" metadata + $this->assertTrue($catalogue->defines('baz', 'domain1')); + $metadata = $catalogue->getMetadata('baz', 'domain1'); + $this->assertNotEmpty($metadata); + $this->assertCount(2, $metadata['notes']); + + $this->assertEquals('x', $metadata['notes'][0]['id']); + $this->assertEquals('x_content', $metadata['notes'][0]['content']); + + $this->assertEquals('target', $metadata['notes'][1]['appliesTo']); + $this->assertEquals('quality', $metadata['notes'][1]['category']); + $this->assertEquals('Fuzzy', $metadata['notes'][1]['content']); + } + + public function testLoadVersion2WithMultiSegmentUnit() + { + $loader = new XliffFileLoader(); + $resource = __DIR__.'/../fixtures/resources-2.0-multi-segment-unit.xlf'; + $catalog = $loader->load($resource, 'en', 'domain1'); + + $this->assertSame('en', $catalog->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalog->getResources()); + $this->assertFalse(libxml_get_last_error()); + + // test for "foo" metadata + $this->assertTrue($catalog->defines('foo', 'domain1')); + $metadata = $catalog->getMetadata('foo', 'domain1'); + $this->assertNotEmpty($metadata); + $this->assertCount(1, $metadata['notes']); + + $this->assertSame('processed', $metadata['notes'][0]['category']); + $this->assertSame('true', $metadata['notes'][0]['content']); + + // test for "bar" metadata + $this->assertTrue($catalog->defines('bar', 'domain1')); + $metadata = $catalog->getMetadata('bar', 'domain1'); + $this->assertNotEmpty($metadata); + $this->assertCount(1, $metadata['notes']); + + $this->assertSame('processed', $metadata['notes'][0]['category']); + $this->assertSame('true', $metadata['notes'][0]['content']); + } + + public function testLoadWithMultipleFileNodes() + { + $loader = new XliffFileLoader(); + $catalogue = $loader->load(__DIR__.'/../fixtures/resources-multi-files.xlf', 'en', 'domain1'); + + $this->assertEquals( + [ + 'source' => 'foo', + 'id' => '1', + 'file' => [ + 'original' => 'file.ext', + ], + ], + $catalogue->getMetadata('foo', 'domain1') + ); + $this->assertEquals( + [ + 'source' => 'test', + 'notes' => [['content' => 'note']], + 'id' => '4', + 'file' => [ + 'original' => 'otherfile.ext', + ], + ], + $catalogue->getMetadata('test', 'domain1') + ); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/YamlFileLoaderTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/YamlFileLoaderTest.php new file mode 100644 index 0000000..b46fff7 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Loader/YamlFileLoaderTest.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Loader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Loader\YamlFileLoader; + +class YamlFileLoaderTest extends TestCase +{ + public function testLoad() + { + $loader = new YamlFileLoader(); + $resource = __DIR__.'/../fixtures/resources.yml'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals(['foo' => 'bar'], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadDoesNothingIfEmpty() + { + $loader = new YamlFileLoader(); + $resource = __DIR__.'/../fixtures/empty.yml'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals([], $catalogue->all('domain1')); + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); + } + + public function testLoadNonExistingResource() + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loader = new YamlFileLoader(); + $resource = __DIR__.'/../fixtures/non-existing.yml'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadThrowsAnExceptionIfFileNotLocal() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new YamlFileLoader(); + $resource = 'http://example.com/resources.yml'; + $loader->load($resource, 'en', 'domain1'); + } + + public function testLoadThrowsAnExceptionIfNotAnArray() + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); + $loader = new YamlFileLoader(); + $resource = __DIR__.'/../fixtures/non-valid.yml'; + $loader->load($resource, 'en', 'domain1'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/LoggingTranslatorTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/LoggingTranslatorTest.php new file mode 100644 index 0000000..450e060 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/LoggingTranslatorTest.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Loader\ArrayLoader; +use Symfony\Component\Translation\LoggingTranslator; +use Symfony\Component\Translation\Translator; + +class LoggingTranslatorTest extends TestCase +{ + public function testTransWithNoTranslationIsLogged() + { + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + $logger->expects($this->exactly(1)) + ->method('warning') + ->with('Translation not found.') + ; + + $translator = new Translator('ar'); + $loggableTranslator = new LoggingTranslator($translator, $logger); + $loggableTranslator->trans('bar'); + } + + /** + * @group legacy + */ + public function testTransChoiceFallbackIsLogged() + { + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + $logger->expects($this->once()) + ->method('debug') + ->with('Translation use fallback catalogue.') + ; + + $translator = new Translator('ar'); + $translator->setFallbackLocales(['en']); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['some_message2' => 'one thing|%count% things'], 'en'); + $loggableTranslator = new LoggingTranslator($translator, $logger); + $loggableTranslator->transChoice('some_message2', 10, ['%count%' => 10]); + } + + /** + * @group legacy + */ + public function testTransChoiceWithNoTranslationIsLogged() + { + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + $logger->expects($this->exactly(1)) + ->method('warning') + ->with('Translation not found.') + ; + + $translator = new Translator('ar'); + $loggableTranslator = new LoggingTranslator($translator, $logger); + $loggableTranslator->transChoice('some_message2', 10, ['%count%' => 10]); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/MessageCatalogueTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/MessageCatalogueTest.php new file mode 100644 index 0000000..b4e3149 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/MessageCatalogueTest.php @@ -0,0 +1,272 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\MessageCatalogue; + +class MessageCatalogueTest extends TestCase +{ + public function testGetLocale() + { + $catalogue = new MessageCatalogue('en'); + + $this->assertEquals('en', $catalogue->getLocale()); + } + + /** + * @group legacy + * @expectedDeprecation Passing "null" to the first argument of the "Symfony\Component\Translation\MessageCatalogue::__construct" method has been deprecated since Symfony 4.4 and will throw an error in 5.0. + */ + public function testGetNullLocale() + { + $catalogue = new MessageCatalogue(null); + + $this->assertNull($catalogue->getLocale()); + } + + public function testGetDomains() + { + $catalogue = new MessageCatalogue('en', ['domain1' => [], 'domain2' => [], 'domain2+intl-icu' => [], 'domain3+intl-icu' => []]); + + $this->assertEquals(['domain1', 'domain2', 'domain3'], $catalogue->getDomains()); + } + + public function testAll() + { + $catalogue = new MessageCatalogue('en', $messages = ['domain1' => ['foo' => 'foo'], 'domain2' => ['bar' => 'bar']]); + + $this->assertEquals(['foo' => 'foo'], $catalogue->all('domain1')); + $this->assertEquals([], $catalogue->all('domain88')); + $this->assertEquals($messages, $catalogue->all()); + + $messages = ['domain1+intl-icu' => ['foo' => 'bar']] + $messages + [ + 'domain2+intl-icu' => ['bar' => 'foo'], + 'domain3+intl-icu' => ['biz' => 'biz'], + ]; + $catalogue = new MessageCatalogue('en', $messages); + + $this->assertEquals(['foo' => 'bar'], $catalogue->all('domain1')); + $this->assertEquals(['bar' => 'foo'], $catalogue->all('domain2')); + $this->assertEquals(['biz' => 'biz'], $catalogue->all('domain3')); + + $messages = [ + 'domain1' => ['foo' => 'bar'], + 'domain2' => ['bar' => 'foo'], + 'domain3' => ['biz' => 'biz'], + ]; + $this->assertEquals($messages, $catalogue->all()); + } + + public function testAllIntICU() + { + $messages = [ + 'domain1+intl-icu' => ['foo' => 'bar'], + 'domain2+intl-icu' => ['bar' => 'foo'], + 'domain2' => ['biz' => 'biz'], + ]; + $catalogue = new MessageCatalogue('en', $messages); + + // separated domains + $this->assertSame(['foo' => 'bar'], $catalogue->all('domain1+intl-icu')); + $this->assertSame(['bar' => 'foo'], $catalogue->all('domain2+intl-icu')); + + // merged, intl-icu ignored + $this->assertSame(['bar' => 'foo', 'biz' => 'biz'], $catalogue->all('domain2')); + + // intl-icu ignored + $messagesExpected = [ + 'domain1' => ['foo' => 'bar'], + 'domain2' => ['bar' => 'foo', 'biz' => 'biz'], + ]; + $this->assertSame($messagesExpected, $catalogue->all()); + } + + public function testHas() + { + $catalogue = new MessageCatalogue('en', ['domain1' => ['foo' => 'foo'], 'domain2+intl-icu' => ['bar' => 'bar']]); + + $this->assertTrue($catalogue->has('foo', 'domain1')); + $this->assertTrue($catalogue->has('bar', 'domain2')); + $this->assertFalse($catalogue->has('bar', 'domain1')); + $this->assertFalse($catalogue->has('foo', 'domain88')); + } + + public function testGetSet() + { + $catalogue = new MessageCatalogue('en', ['domain1' => ['foo' => 'foo'], 'domain2' => ['bar' => 'bar'], 'domain2+intl-icu' => ['bar' => 'foo']]); + $catalogue->set('foo1', 'foo1', 'domain1'); + + $this->assertEquals('foo', $catalogue->get('foo', 'domain1')); + $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1')); + $this->assertEquals('foo', $catalogue->get('bar', 'domain2')); + } + + public function testAdd() + { + $catalogue = new MessageCatalogue('en', ['domain1' => ['foo' => 'foo'], 'domain2' => ['bar' => 'bar']]); + $catalogue->add(['foo1' => 'foo1'], 'domain1'); + + $this->assertEquals('foo', $catalogue->get('foo', 'domain1')); + $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1')); + + $catalogue->add(['foo' => 'bar'], 'domain1'); + $this->assertEquals('bar', $catalogue->get('foo', 'domain1')); + $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1')); + + $catalogue->add(['foo' => 'bar'], 'domain88'); + $this->assertEquals('bar', $catalogue->get('foo', 'domain88')); + } + + public function testReplace() + { + $catalogue = new MessageCatalogue('en', ['domain1' => ['foo' => 'foo'], 'domain1+intl-icu' => ['bar' => 'bar']]); + $catalogue->replace($messages = ['foo1' => 'foo1'], 'domain1'); + + $this->assertEquals($messages, $catalogue->all('domain1')); + } + + public function testAddCatalogue() + { + $r = $this->getMockBuilder('Symfony\Component\Config\Resource\ResourceInterface')->getMock(); + $r->expects($this->any())->method('__toString')->willReturn('r'); + + $r1 = $this->getMockBuilder('Symfony\Component\Config\Resource\ResourceInterface')->getMock(); + $r1->expects($this->any())->method('__toString')->willReturn('r1'); + + $catalogue = new MessageCatalogue('en', ['domain1' => ['foo' => 'foo']]); + $catalogue->addResource($r); + + $catalogue1 = new MessageCatalogue('en', ['domain1' => ['foo1' => 'foo1'], 'domain2+intl-icu' => ['bar' => 'bar']]); + $catalogue1->addResource($r1); + + $catalogue->addCatalogue($catalogue1); + + $this->assertEquals('foo', $catalogue->get('foo', 'domain1')); + $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1')); + $this->assertEquals('bar', $catalogue->get('bar', 'domain2')); + $this->assertEquals('bar', $catalogue->get('bar', 'domain2+intl-icu')); + + $this->assertEquals([$r, $r1], $catalogue->getResources()); + } + + public function testAddFallbackCatalogue() + { + $r = $this->getMockBuilder('Symfony\Component\Config\Resource\ResourceInterface')->getMock(); + $r->expects($this->any())->method('__toString')->willReturn('r'); + + $r1 = $this->getMockBuilder('Symfony\Component\Config\Resource\ResourceInterface')->getMock(); + $r1->expects($this->any())->method('__toString')->willReturn('r1'); + + $r2 = $this->getMockBuilder('Symfony\Component\Config\Resource\ResourceInterface')->getMock(); + $r2->expects($this->any())->method('__toString')->willReturn('r2'); + + $catalogue = new MessageCatalogue('fr_FR', ['domain1' => ['foo' => 'foo'], 'domain2' => ['bar' => 'bar']]); + $catalogue->addResource($r); + + $catalogue1 = new MessageCatalogue('fr', ['domain1' => ['foo' => 'bar', 'foo1' => 'foo1']]); + $catalogue1->addResource($r1); + + $catalogue2 = new MessageCatalogue('en'); + $catalogue2->addResource($r2); + + $catalogue->addFallbackCatalogue($catalogue1); + $catalogue1->addFallbackCatalogue($catalogue2); + + $this->assertEquals('foo', $catalogue->get('foo', 'domain1')); + $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1')); + + $this->assertEquals([$r, $r1, $r2], $catalogue->getResources()); + } + + public function testAddFallbackCatalogueWithParentCircularReference() + { + $this->expectException('Symfony\Component\Translation\Exception\LogicException'); + $main = new MessageCatalogue('en_US'); + $fallback = new MessageCatalogue('fr_FR'); + + $fallback->addFallbackCatalogue($main); + $main->addFallbackCatalogue($fallback); + } + + public function testAddFallbackCatalogueWithFallbackCircularReference() + { + $this->expectException('Symfony\Component\Translation\Exception\LogicException'); + $fr = new MessageCatalogue('fr'); + $en = new MessageCatalogue('en'); + $es = new MessageCatalogue('es'); + + $fr->addFallbackCatalogue($en); + $es->addFallbackCatalogue($en); + $en->addFallbackCatalogue($fr); + } + + public function testAddCatalogueWhenLocaleIsNotTheSameAsTheCurrentOne() + { + $this->expectException('Symfony\Component\Translation\Exception\LogicException'); + $catalogue = new MessageCatalogue('en'); + $catalogue->addCatalogue(new MessageCatalogue('fr', [])); + } + + public function testGetAddResource() + { + $catalogue = new MessageCatalogue('en'); + $r = $this->getMockBuilder('Symfony\Component\Config\Resource\ResourceInterface')->getMock(); + $r->expects($this->any())->method('__toString')->willReturn('r'); + $catalogue->addResource($r); + $catalogue->addResource($r); + $r1 = $this->getMockBuilder('Symfony\Component\Config\Resource\ResourceInterface')->getMock(); + $r1->expects($this->any())->method('__toString')->willReturn('r1'); + $catalogue->addResource($r1); + + $this->assertEquals([$r, $r1], $catalogue->getResources()); + } + + public function testMetadataDelete() + { + $catalogue = new MessageCatalogue('en'); + $this->assertEquals([], $catalogue->getMetadata('', ''), 'Metadata is empty'); + $catalogue->deleteMetadata('key', 'messages'); + $catalogue->deleteMetadata('', 'messages'); + $catalogue->deleteMetadata(); + } + + public function testMetadataSetGetDelete() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->setMetadata('key', 'value'); + $this->assertEquals('value', $catalogue->getMetadata('key', 'messages'), "Metadata 'key' = 'value'"); + + $catalogue->setMetadata('key2', []); + $this->assertEquals([], $catalogue->getMetadata('key2', 'messages'), 'Metadata key2 is array'); + + $catalogue->deleteMetadata('key2', 'messages'); + $this->assertNull($catalogue->getMetadata('key2', 'messages'), 'Metadata key2 should is deleted.'); + + $catalogue->deleteMetadata('key2', 'domain'); + $this->assertNull($catalogue->getMetadata('key2', 'domain'), 'Metadata key2 should is deleted.'); + } + + public function testMetadataMerge() + { + $cat1 = new MessageCatalogue('en'); + $cat1->setMetadata('a', 'b'); + $this->assertEquals(['messages' => ['a' => 'b']], $cat1->getMetadata('', ''), 'Cat1 contains messages metadata.'); + + $cat2 = new MessageCatalogue('en'); + $cat2->setMetadata('b', 'c', 'domain'); + $this->assertEquals(['domain' => ['b' => 'c']], $cat2->getMetadata('', ''), 'Cat2 contains domain metadata.'); + + $cat1->addCatalogue($cat2); + $this->assertEquals(['messages' => ['a' => 'b'], 'domain' => ['b' => 'c']], $cat1->getMetadata('', ''), 'Cat1 contains merged metadata.'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/MessageSelectorTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/MessageSelectorTest.php new file mode 100644 index 0000000..20609dd --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/MessageSelectorTest.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\MessageSelector; + +/** + * @group legacy + */ +class MessageSelectorTest extends TestCase +{ + /** + * @dataProvider getChooseTests + */ + public function testChoose($expected, $id, $number) + { + $selector = new MessageSelector(); + + $this->assertEquals($expected, $selector->choose($id, $number, 'en')); + } + + public function testReturnMessageIfExactlyOneStandardRuleIsGiven() + { + $selector = new MessageSelector(); + + $this->assertEquals('There are two apples', $selector->choose('There are two apples', 2, 'en')); + } + + /** + * @dataProvider getNonMatchingMessages + */ + public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number) + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidArgumentException'); + $selector = new MessageSelector(); + + $selector->choose($id, $number, 'en'); + } + + public function getNonMatchingMessages() + { + return [ + ['{0} There are no apples|{1} There is one apple', 2], + ['{1} There is one apple|]1,Inf] There are %count% apples', 0], + ['{1} There is one apple|]2,Inf] There are %count% apples', 2], + ['{0} There are no apples|There is one apple', 2], + ]; + } + + public function getChooseTests() + { + return [ + ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], + ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], + ['There are no apples', '{0}There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], + + ['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1], + + ['There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10], + ['There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10], + ['There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10], + + ['There are %count% apples', 'There is one apple|There are %count% apples', 0], + ['There is one apple', 'There is one apple|There are %count% apples', 1], + ['There are %count% apples', 'There is one apple|There are %count% apples', 10], + + ['There are %count% apples', 'one: There is one apple|more: There are %count% apples', 0], + ['There is one apple', 'one: There is one apple|more: There are %count% apples', 1], + ['There are %count% apples', 'one: There is one apple|more: There are %count% apples', 10], + + ['There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0], + ['There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1], + ['There are %count% apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10], + + ['', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0], + ['', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1], + + // Indexed only tests which are Gettext PoFile* compatible strings. + ['There are %count% apples', 'There is one apple|There are %count% apples', 0], + ['There is one apple', 'There is one apple|There are %count% apples', 1], + ['There are %count% apples', 'There is one apple|There are %count% apples', 2], + + // Tests for float numbers + ['There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7], + ['There is one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1], + ['There is more than one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1.7], + ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0], + ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0.0], + ['There are no apples', '{0.0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0], + + // Test texts with new-lines + // with double-quotes and \n in id & double-quotes and actual newlines in text + ["This is a text with a\n new-line in it. Selector = 0.", '{0}This is a text with a + new-line in it. Selector = 0.|{1}This is a text with a + new-line in it. Selector = 1.|[1,Inf]This is a text with a + new-line in it. Selector > 1.', 0], + // with double-quotes and \n in id and single-quotes and actual newlines in text + ["This is a text with a\n new-line in it. Selector = 1.", '{0}This is a text with a + new-line in it. Selector = 0.|{1}This is a text with a + new-line in it. Selector = 1.|[1,Inf]This is a text with a + new-line in it. Selector > 1.', 1], + ["This is a text with a\n new-line in it. Selector > 1.", '{0}This is a text with a + new-line in it. Selector = 0.|{1}This is a text with a + new-line in it. Selector = 1.|[1,Inf]This is a text with a + new-line in it. Selector > 1.', 5], + // with double-quotes and id split accros lines + ['This is a text with a + new-line in it. Selector = 1.', '{0}This is a text with a + new-line in it. Selector = 0.|{1}This is a text with a + new-line in it. Selector = 1.|[1,Inf]This is a text with a + new-line in it. Selector > 1.', 1], + // with single-quotes and id split accros lines + ['This is a text with a + new-line in it. Selector > 1.', '{0}This is a text with a + new-line in it. Selector = 0.|{1}This is a text with a + new-line in it. Selector = 1.|[1,Inf]This is a text with a + new-line in it. Selector > 1.', 5], + // with single-quotes and \n in text + ['This is a text with a\nnew-line in it. Selector = 0.', '{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.', 0], + // with double-quotes and id split accros lines + ["This is a text with a\nnew-line in it. Selector = 1.", "{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.", 1], + // esacape pipe + ['This is a text with | in it. Selector = 0.', '{0}This is a text with || in it. Selector = 0.|{1}This is a text with || in it. Selector = 1.', 0], + // Empty plural set (2 plural forms) from a .PO file + ['', '|', 1], + // Empty plural set (3 plural forms) from a .PO file + ['', '||', 1], + ]; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/PluralizationRulesTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/PluralizationRulesTest.php new file mode 100644 index 0000000..4b8bdff --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/PluralizationRulesTest.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\PluralizationRules; + +/** + * Test should cover all languages mentioned on http://translate.sourceforge.net/wiki/l10n/pluralforms + * and Plural forms mentioned on http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms. + * + * See also https://developer.mozilla.org/en/Localization_and_Plurals which mentions 15 rules having a maximum of 6 forms. + * The mozilla code is also interesting to check for. + * + * As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199 + * + * The goal to cover all languages is to far fetched so this test case is smaller. + * + * @author Clemens Tolboom clemens@build2be.nl + * + * @group legacy + */ +class PluralizationRulesTest extends TestCase +{ + /** + * We test failed langcode here. + * + * TODO: The languages mentioned in the data provide need to get fixed somehow within PluralizationRules. + * + * @dataProvider failingLangcodes + */ + public function testFailedLangcodes($nplural, $langCodes) + { + $matrix = $this->generateTestData($langCodes); + $this->validateMatrix($nplural, $matrix, false); + } + + /** + * @dataProvider successLangcodes + */ + public function testLangcodes($nplural, $langCodes) + { + $matrix = $this->generateTestData($langCodes); + $this->validateMatrix($nplural, $matrix); + } + + /** + * This array should contain all currently known langcodes. + * + * As it is impossible to have this ever complete we should try as hard as possible to have it almost complete. + */ + public function successLangcodes(): array + { + return [ + ['1', ['ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky']], + ['2', ['nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM']], + ['3', ['be', 'bs', 'cs', 'hr']], + ['4', ['cy', 'mt', 'sl']], + ['6', ['ar']], + ]; + } + + /** + * This array should be at least empty within the near future. + * + * This both depends on a complete list trying to add above as understanding + * the plural rules of the current failing languages. + * + * @return array with nplural together with langcodes + */ + public function failingLangcodes(): array + { + return [ + ['1', ['fa']], + ['2', ['jbo']], + ['3', ['cbs']], + ['4', ['gd', 'kw']], + ['5', ['ga']], + ]; + } + + /** + * We validate only on the plural coverage. Thus the real rules is not tested. + * + * @param string $nplural Plural expected + * @param array $matrix Containing langcodes and their plural index values + * @param bool $expectSuccess + */ + protected function validateMatrix($nplural, $matrix, $expectSuccess = true) + { + foreach ($matrix as $langCode => $data) { + $indexes = array_flip($data); + if ($expectSuccess) { + $this->assertEquals($nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms."); + } else { + $this->assertNotEquals((int) $nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms."); + } + } + } + + protected function generateTestData($langCodes) + { + $matrix = []; + foreach ($langCodes as $langCode) { + for ($count = 0; $count < 200; ++$count) { + $plural = PluralizationRules::get($count, $langCode); + $matrix[$langCode][$count] = $plural; + } + } + + return $matrix; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/TranslatorCacheTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/TranslatorCacheTest.php new file mode 100644 index 0000000..8efa318 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/TranslatorCacheTest.php @@ -0,0 +1,332 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests; + +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Resource\SelfCheckingResourceInterface; +use Symfony\Component\Translation\Loader\ArrayLoader; +use Symfony\Component\Translation\Loader\LoaderInterface; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Translator; + +class TranslatorCacheTest extends TestCase +{ + protected $tmpDir; + + protected function setUp(): void + { + $this->tmpDir = sys_get_temp_dir().'/sf_translation'; + $this->deleteTmpDir(); + } + + protected function tearDown(): void + { + $this->deleteTmpDir(); + } + + protected function deleteTmpDir() + { + if (!file_exists($dir = $this->tmpDir)) { + return; + } + + $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->tmpDir), \RecursiveIteratorIterator::CHILD_FIRST); + foreach ($iterator as $path) { + if (preg_match('#[/\\\\]\.\.?$#', $path->__toString())) { + continue; + } + if ($path->isDir()) { + rmdir($path->__toString()); + } else { + unlink($path->__toString()); + } + } + rmdir($this->tmpDir); + } + + /** + * @dataProvider runForDebugAndProduction + */ + public function testThatACacheIsUsed($debug) + { + $locale = 'any_locale'; + $format = 'some_format'; + $msgid = 'test'; + + // Prime the cache + $translator = new Translator($locale, null, $this->tmpDir, $debug); + $translator->addLoader($format, new ArrayLoader()); + $translator->addResource($format, [$msgid => 'OK'], $locale); + $translator->addResource($format, [$msgid.'+intl' => 'OK'], $locale, 'messages+intl-icu'); + $translator->trans($msgid); + $translator->trans($msgid.'+intl', [], 'messages+intl-icu'); + + // Try again and see we get a valid result whilst no loader can be used + $translator = new Translator($locale, null, $this->tmpDir, $debug); + $translator->addLoader($format, $this->createFailingLoader()); + $translator->addResource($format, [$msgid => 'OK'], $locale); + $translator->addResource($format, [$msgid.'+intl' => 'OK'], $locale, 'messages+intl-icu'); + $this->assertEquals('OK', $translator->trans($msgid), '-> caching does not work in '.($debug ? 'debug' : 'production')); + $this->assertEquals('OK', $translator->trans($msgid.'+intl', [], 'messages+intl-icu')); + } + + public function testCatalogueIsReloadedWhenResourcesAreNoLongerFresh() + { + /* + * The testThatACacheIsUsed() test showed that we don't need the loader as long as the cache + * is fresh. + * + * Now we add a Resource that is never fresh and make sure that the + * cache is discarded (the loader is called twice). + * + * We need to run this for debug=true only because in production the cache + * will never be revalidated. + */ + + $locale = 'any_locale'; + $format = 'some_format'; + $msgid = 'test'; + + $catalogue = new MessageCatalogue($locale, []); + $catalogue->addResource(new StaleResource()); // better use a helper class than a mock, because it gets serialized in the cache and re-loaded + + /** @var LoaderInterface|MockObject $loader */ + $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock(); + $loader + ->expects($this->exactly(2)) + ->method('load') + ->willReturn($catalogue) + ; + + // 1st pass + $translator = new Translator($locale, null, $this->tmpDir, true); + $translator->addLoader($format, $loader); + $translator->addResource($format, null, $locale); + $translator->trans($msgid); + + // 2nd pass + $translator = new Translator($locale, null, $this->tmpDir, true); + $translator->addLoader($format, $loader); + $translator->addResource($format, null, $locale); + $translator->trans($msgid); + } + + /** + * @dataProvider runForDebugAndProduction + */ + public function testDifferentTranslatorsForSameLocaleDoNotOverwriteEachOthersCache($debug) + { + /* + * Similar to the previous test. After we used the second translator, make + * sure there's still a usable cache for the first one. + */ + + $locale = 'any_locale'; + $format = 'some_format'; + $msgid = 'test'; + + // Create a Translator and prime its cache + $translator = new Translator($locale, null, $this->tmpDir, $debug); + $translator->addLoader($format, new ArrayLoader()); + $translator->addResource($format, [$msgid => 'OK'], $locale); + $translator->trans($msgid); + + // Create another Translator with a different catalogue for the same locale + $translator = new Translator($locale, null, $this->tmpDir, $debug); + $translator->addLoader($format, new ArrayLoader()); + $translator->addResource($format, [$msgid => 'FAIL'], $locale); + $translator->trans($msgid); + + // Now the first translator must still have a usable cache. + $translator = new Translator($locale, null, $this->tmpDir, $debug); + $translator->addLoader($format, $this->createFailingLoader()); + $translator->addResource($format, [$msgid => 'OK'], $locale); + $this->assertEquals('OK', $translator->trans($msgid), '-> the cache was overwritten by another translator instance in '.($debug ? 'debug' : 'production')); + } + + public function testGeneratedCacheFilesAreOnlyBelongRequestedLocales() + { + $translator = new Translator('a', null, $this->tmpDir); + $translator->setFallbackLocales(['b']); + $translator->trans('bar'); + + $cachedFiles = glob($this->tmpDir.'/*.php'); + + $this->assertCount(1, $cachedFiles); + } + + public function testDifferentCacheFilesAreUsedForDifferentSetsOfFallbackLocales() + { + /* + * Because the cache file contains a catalogue including all of its fallback + * catalogues, we must take the set of fallback locales into consideration when + * loading a catalogue from the cache. + */ + $translator = new Translator('a', null, $this->tmpDir); + $translator->setFallbackLocales(['b']); + + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foo (a)'], 'a'); + $translator->addResource('array', ['bar' => 'bar (b)'], 'b'); + + $this->assertEquals('bar (b)', $translator->trans('bar')); + + // Remove fallback locale + $translator->setFallbackLocales([]); + $this->assertEquals('bar', $translator->trans('bar')); + + // Use a fresh translator with no fallback locales, result should be the same + $translator = new Translator('a', null, $this->tmpDir); + + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foo (a)'], 'a'); + $translator->addResource('array', ['bar' => 'bar (b)'], 'b'); + + $this->assertEquals('bar', $translator->trans('bar')); + } + + public function testPrimaryAndFallbackCataloguesContainTheSameMessagesRegardlessOfCaching() + { + /* + * As a safeguard against potential BC breaks, make sure that primary and fallback + * catalogues (reachable via getFallbackCatalogue()) always contain the full set of + * messages provided by the loader. This must also be the case when these catalogues + * are (internally) read from a cache. + * + * Optimizations inside the translator must not change this behavior. + */ + + /* + * Create a translator that loads two catalogues for two different locales. + * The catalogues contain distinct sets of messages. + */ + $translator = new Translator('a', null, $this->tmpDir); + $translator->setFallbackLocales(['b']); + + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foo (a)'], 'a'); + $translator->addResource('array', ['foo' => 'foo (b)'], 'b'); + $translator->addResource('array', ['bar' => 'bar (b)'], 'b'); + $translator->addResource('array', ['baz' => 'baz (b)'], 'b', 'messages+intl-icu'); + + $catalogue = $translator->getCatalogue('a'); + $this->assertFalse($catalogue->defines('bar')); // Sure, the "a" catalogue does not contain that message. + + $fallback = $catalogue->getFallbackCatalogue(); + $this->assertTrue($fallback->defines('foo')); // "foo" is present in "a" and "b" + + /* + * Now, repeat the same test. + * Behind the scenes, the cache is used. But that should not matter, right? + */ + $translator = new Translator('a', null, $this->tmpDir); + $translator->setFallbackLocales(['b']); + + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foo (a)'], 'a'); + $translator->addResource('array', ['foo' => 'foo (b)'], 'b'); + $translator->addResource('array', ['bar' => 'bar (b)'], 'b'); + $translator->addResource('array', ['baz' => 'baz (b)'], 'b', 'messages+intl-icu'); + + $catalogue = $translator->getCatalogue('a'); + $this->assertFalse($catalogue->defines('bar')); + + $fallback = $catalogue->getFallbackCatalogue(); + $this->assertTrue($fallback->defines('foo')); + $this->assertTrue($fallback->defines('baz', 'messages+intl-icu')); + } + + public function testRefreshCacheWhenResourcesAreNoLongerFresh() + { + $resource = $this->getMockBuilder('Symfony\Component\Config\Resource\SelfCheckingResourceInterface')->getMock(); + $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock(); + $resource->method('isFresh')->willReturn(false); + $loader + ->expects($this->exactly(2)) + ->method('load') + ->willReturn($this->getCatalogue('fr', [], [$resource])); + + // prime the cache + $translator = new Translator('fr', null, $this->tmpDir, true); + $translator->addLoader('loader', $loader); + $translator->addResource('loader', 'foo', 'fr'); + $translator->trans('foo'); + + // prime the cache second time + $translator = new Translator('fr', null, $this->tmpDir, true); + $translator->addLoader('loader', $loader); + $translator->addResource('loader', 'foo', 'fr'); + $translator->trans('foo'); + } + + public function testCachedCatalogueIsReDumpedWhenCacheVaryChange() + { + $translator = new Translator('a', null, $this->tmpDir, false, []); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'bar'], 'a', 'messages'); + + // Cached catalogue is dumped + $this->assertSame('bar', $translator->trans('foo', [], 'messages', 'a')); + + $translator = new Translator('a', null, $this->tmpDir, false, ['vary']); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'ccc'], 'a', 'messages'); + + $this->assertSame('ccc', $translator->trans('foo', [], 'messages', 'a')); + } + + protected function getCatalogue($locale, $messages, $resources = []) + { + $catalogue = new MessageCatalogue($locale); + foreach ($messages as $key => $translation) { + $catalogue->set($key, $translation); + } + foreach ($resources as $resource) { + $catalogue->addResource($resource); + } + + return $catalogue; + } + + public function runForDebugAndProduction() + { + return [[true], [false]]; + } + + private function createFailingLoader(): LoaderInterface + { + $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock(); + $loader + ->expects($this->never()) + ->method('load'); + + return $loader; + } +} + +class StaleResource implements SelfCheckingResourceInterface +{ + public function isFresh($timestamp): bool + { + return false; + } + + public function getResource() + { + } + + public function __toString(): string + { + return ''; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/TranslatorTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/TranslatorTest.php new file mode 100644 index 0000000..764f31b --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/TranslatorTest.php @@ -0,0 +1,706 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Loader\ArrayLoader; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Translator; + +class TranslatorTest extends TestCase +{ + /** + * @dataProvider getInvalidLocalesTests + */ + public function testConstructorInvalidLocale($locale) + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidArgumentException'); + new Translator($locale); + } + + /** + * @dataProvider getValidLocalesTests + */ + public function testConstructorValidLocale($locale) + { + $translator = new Translator($locale); + + $this->assertSame($locale, $translator->getLocale()); + } + + /** + * @group legacy + */ + public function testConstructorWithoutLocale() + { + $translator = new Translator(null); + + $this->assertNull($translator->getLocale()); + } + + public function testSetGetLocale() + { + $translator = new Translator('en'); + + $this->assertEquals('en', $translator->getLocale()); + + $translator->setLocale('fr'); + $this->assertEquals('fr', $translator->getLocale()); + } + + /** + * @dataProvider getInvalidLocalesTests + */ + public function testSetInvalidLocale($locale) + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidArgumentException'); + $translator = new Translator('fr'); + $translator->setLocale($locale); + } + + /** + * @dataProvider getValidLocalesTests + */ + public function testSetValidLocale($locale) + { + $translator = new Translator($locale); + $translator->setLocale($locale); + + $this->assertEquals($locale, $translator->getLocale()); + } + + /** + * @group legacy + */ + public function testSetNullLocale() + { + $translator = new Translator('en'); + $translator->setLocale(null); + + $this->assertNull($translator->getLocale()); + } + + public function testGetCatalogue() + { + $translator = new Translator('en'); + + $this->assertEquals(new MessageCatalogue('en'), $translator->getCatalogue()); + + $translator->setLocale('fr'); + $this->assertEquals(new MessageCatalogue('fr'), $translator->getCatalogue('fr')); + } + + public function testGetCatalogueReturnsConsolidatedCatalogue() + { + /* + * This will be useful once we refactor so that different domains will be loaded lazily (on-demand). + * In that case, getCatalogue() will probably have to load all missing domains in order to return + * one complete catalogue. + */ + + $locale = 'whatever'; + $translator = new Translator($locale); + $translator->addLoader('loader-a', new ArrayLoader()); + $translator->addLoader('loader-b', new ArrayLoader()); + $translator->addResource('loader-a', ['foo' => 'foofoo'], $locale, 'domain-a'); + $translator->addResource('loader-b', ['bar' => 'foobar'], $locale, 'domain-b'); + + /* + * Test that we get a single catalogue comprising messages + * from different loaders and different domains + */ + $catalogue = $translator->getCatalogue($locale); + $this->assertTrue($catalogue->defines('foo', 'domain-a')); + $this->assertTrue($catalogue->defines('bar', 'domain-b')); + } + + public function testSetFallbackLocales() + { + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foofoo'], 'en'); + $translator->addResource('array', ['bar' => 'foobar'], 'fr'); + + // force catalogue loading + $translator->trans('bar'); + + $translator->setFallbackLocales(['fr']); + $this->assertEquals('foobar', $translator->trans('bar')); + } + + public function testSetFallbackLocalesMultiple() + { + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foo (en)'], 'en'); + $translator->addResource('array', ['bar' => 'bar (fr)'], 'fr'); + + // force catalogue loading + $translator->trans('bar'); + + $translator->setFallbackLocales(['fr_FR', 'fr']); + $this->assertEquals('bar (fr)', $translator->trans('bar')); + } + + /** + * @dataProvider getInvalidLocalesTests + */ + public function testSetFallbackInvalidLocales($locale) + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidArgumentException'); + $translator = new Translator('fr'); + $translator->setFallbackLocales(['fr', $locale]); + } + + /** + * @dataProvider getValidLocalesTests + */ + public function testSetFallbackValidLocales($locale) + { + $translator = new Translator($locale); + $translator->setFallbackLocales(['fr', $locale]); + // no assertion. this method just asserts that no exception is thrown + $this->addToAssertionCount(1); + } + + /** + * @group legacy + */ + public function testSetNullFallbackLocale() + { + $translator = new Translator('en'); + $translator->setFallbackLocales(['fr', null]); + // no assertion. this method just asserts that no exception is thrown + $this->addToAssertionCount(1); + } + + public function testTransWithFallbackLocale() + { + $translator = new Translator('fr_FR'); + $translator->setFallbackLocales(['en']); + + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['bar' => 'foobar'], 'en'); + + $this->assertEquals('foobar', $translator->trans('bar')); + } + + /** + * @dataProvider getInvalidLocalesTests + */ + public function testAddResourceInvalidLocales($locale) + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidArgumentException'); + $translator = new Translator('fr'); + $translator->addResource('array', ['foo' => 'foofoo'], $locale); + } + + /** + * @dataProvider getValidLocalesTests + */ + public function testAddResourceValidLocales($locale) + { + $translator = new Translator('fr'); + $translator->addResource('array', ['foo' => 'foofoo'], $locale); + // no assertion. this method just asserts that no exception is thrown + $this->addToAssertionCount(1); + } + + /** + * @group legacy + * @expectedDeprecation Passing "null" to the third argument of the "Symfony\Component\Translation\Translator::addResource" method has been deprecated since Symfony 4.4 and will throw an error in 5.0. + */ + public function testAddResourceNull() + { + $translator = new Translator('fr'); + $translator->addResource('array', ['foo' => 'foofoo'], null); + } + + public function testAddResourceAfterTrans() + { + $translator = new Translator('fr'); + $translator->addLoader('array', new ArrayLoader()); + + $translator->setFallbackLocales(['en']); + + $translator->addResource('array', ['foo' => 'foofoo'], 'en'); + $this->assertEquals('foofoo', $translator->trans('foo')); + + $translator->addResource('array', ['bar' => 'foobar'], 'en'); + $this->assertEquals('foobar', $translator->trans('bar')); + } + + /** + * @dataProvider getTransFileTests + */ + public function testTransWithoutFallbackLocaleFile($format, $loader) + { + $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException'); + $loaderClass = 'Symfony\\Component\\Translation\\Loader\\'.$loader; + $translator = new Translator('en'); + $translator->addLoader($format, new $loaderClass()); + $translator->addResource($format, __DIR__.'/fixtures/non-existing', 'en'); + $translator->addResource($format, __DIR__.'/fixtures/resources.'.$format, 'en'); + + // force catalogue loading + $translator->trans('foo'); + } + + /** + * @dataProvider getTransFileTests + */ + public function testTransWithFallbackLocaleFile($format, $loader) + { + $loaderClass = 'Symfony\\Component\\Translation\\Loader\\'.$loader; + $translator = new Translator('en_GB'); + $translator->addLoader($format, new $loaderClass()); + $translator->addResource($format, __DIR__.'/fixtures/non-existing', 'en_GB'); + $translator->addResource($format, __DIR__.'/fixtures/resources.'.$format, 'en', 'resources'); + + $this->assertEquals('bar', $translator->trans('foo', [], 'resources')); + } + + public function testTransWithIcuFallbackLocale() + { + $translator = new Translator('en_GB'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foofoo'], 'en_GB'); + $translator->addResource('array', ['bar' => 'foobar'], 'en_001'); + $translator->addResource('array', ['baz' => 'foobaz'], 'en'); + $this->assertSame('foofoo', $translator->trans('foo')); + $this->assertSame('foobar', $translator->trans('bar')); + $this->assertSame('foobaz', $translator->trans('baz')); + } + + public function testTransWithIcuVariantFallbackLocale() + { + $translator = new Translator('en_GB_scouse'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foofoo'], 'en_GB_scouse'); + $translator->addResource('array', ['bar' => 'foobar'], 'en_GB'); + $translator->addResource('array', ['baz' => 'foobaz'], 'en_001'); + $translator->addResource('array', ['qux' => 'fooqux'], 'en'); + $this->assertSame('foofoo', $translator->trans('foo')); + $this->assertSame('foobar', $translator->trans('bar')); + $this->assertSame('foobaz', $translator->trans('baz')); + $this->assertSame('fooqux', $translator->trans('qux')); + } + + public function testTransWithIcuRootFallbackLocale() + { + $translator = new Translator('az_Cyrl'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foofoo'], 'az_Cyrl'); + $translator->addResource('array', ['bar' => 'foobar'], 'az'); + $this->assertSame('foofoo', $translator->trans('foo')); + $this->assertSame('bar', $translator->trans('bar')); + } + + /** + * @dataProvider getFallbackLocales + */ + public function testTransWithFallbackLocaleBis($expectedLocale, $locale) + { + $translator = new Translator($locale); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foofoo'], $locale); + $translator->addResource('array', ['bar' => 'foobar'], $expectedLocale); + $this->assertEquals('foobar', $translator->trans('bar')); + } + + public function getFallbackLocales() + { + $locales = [ + ['en', 'en_US'], + ['en', 'en-US'], + ['sl_Latn_IT', 'sl_Latn_IT_nedis'], + ['sl_Latn', 'sl_Latn_IT'], + ]; + + if (\function_exists('locale_parse')) { + $locales[] = ['sl_Latn_IT', 'sl-Latn-IT-nedis']; + $locales[] = ['sl_Latn', 'sl-Latn-IT']; + } else { + $locales[] = ['sl-Latn-IT', 'sl-Latn-IT-nedis']; + $locales[] = ['sl-Latn', 'sl-Latn-IT']; + } + + return $locales; + } + + public function testTransWithFallbackLocaleTer() + { + $translator = new Translator('fr_FR'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foo (en_US)'], 'en_US'); + $translator->addResource('array', ['bar' => 'bar (en)'], 'en'); + + $translator->setFallbackLocales(['en_US', 'en']); + + $this->assertEquals('foo (en_US)', $translator->trans('foo')); + $this->assertEquals('bar (en)', $translator->trans('bar')); + } + + public function testTransNonExistentWithFallback() + { + $translator = new Translator('fr'); + $translator->setFallbackLocales(['en']); + $translator->addLoader('array', new ArrayLoader()); + $this->assertEquals('non-existent', $translator->trans('non-existent')); + } + + public function testWhenAResourceHasNoRegisteredLoader() + { + $this->expectException('Symfony\Component\Translation\Exception\RuntimeException'); + $translator = new Translator('en'); + $translator->addResource('array', ['foo' => 'foofoo'], 'en'); + + $translator->trans('foo'); + } + + public function testNestedFallbackCatalogueWhenUsingMultipleLocales() + { + $translator = new Translator('fr'); + $translator->setFallbackLocales(['ru', 'en']); + + $translator->getCatalogue('fr'); + + $this->assertNotNull($translator->getCatalogue('ru')->getFallbackCatalogue()); + } + + public function testFallbackCatalogueResources() + { + $translator = new Translator('en_GB'); + $translator->addLoader('yml', new \Symfony\Component\Translation\Loader\YamlFileLoader()); + $translator->addResource('yml', __DIR__.'/fixtures/empty.yml', 'en_GB'); + $translator->addResource('yml', __DIR__.'/fixtures/resources.yml', 'en'); + + // force catalogue loading + $this->assertEquals('bar', $translator->trans('foo', [])); + + $resources = $translator->getCatalogue('en')->getResources(); + $this->assertCount(1, $resources); + $this->assertContains(__DIR__.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'resources.yml', $resources); + + $resources = $translator->getCatalogue('en_GB')->getResources(); + $this->assertCount(2, $resources); + $this->assertContains(__DIR__.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'empty.yml', $resources); + $this->assertContains(__DIR__.\DIRECTORY_SEPARATOR.'fixtures'.\DIRECTORY_SEPARATOR.'resources.yml', $resources); + } + + /** + * @dataProvider getTransTests + */ + public function testTrans($expected, $id, $translation, $parameters, $locale, $domain) + { + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', [(string) $id => $translation], $locale, $domain); + + $this->assertEquals($expected, $translator->trans($id, $parameters, $domain, $locale)); + } + + /** + * @dataProvider getInvalidLocalesTests + */ + public function testTransInvalidLocale($locale) + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidArgumentException'); + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foofoo'], 'en'); + + $translator->trans('foo', [], '', $locale); + } + + /** + * @dataProvider getValidLocalesTests + */ + public function testTransValidLocale($locale) + { + $translator = new Translator($locale); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['test' => 'OK'], $locale); + + $this->assertEquals('OK', $translator->trans('test')); + $this->assertEquals('OK', $translator->trans('test', [], null, $locale)); + } + + /** + * @group legacy + * @expectedDeprecation Passing "null" to the third argument of the "Symfony\Component\Translation\Translator::addResource" method has been deprecated since Symfony 4.4 and will throw an error in 5.0. + */ + public function testTransNullLocale() + { + $translator = new Translator(null); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['test' => 'OK'], null); + } + + /** + * @dataProvider getFlattenedTransTests + */ + public function testFlattenedTrans($expected, $messages, $id) + { + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', $messages, 'fr', ''); + + $this->assertEquals($expected, $translator->trans($id, [], '', 'fr')); + } + + /** + * @dataProvider getTransChoiceTests + * @group legacy + */ + public function testTransChoice($expected, $id, $translation, $number, $parameters, $locale, $domain) + { + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', [(string) $id => $translation], $locale, $domain); + + $this->assertEquals($expected, $translator->transChoice($id, $number, $parameters, $domain, $locale)); + } + + /** + * @dataProvider getInvalidLocalesTests + * @group legacy + */ + public function testTransChoiceInvalidLocale($locale) + { + $this->expectException('Symfony\Component\Translation\Exception\InvalidArgumentException'); + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foofoo'], 'en'); + + $translator->transChoice('foo', 1, [], '', $locale); + } + + /** + * @dataProvider getValidLocalesTests + * @group legacy + */ + public function testTransChoiceValidLocale($locale) + { + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foofoo'], 'en'); + + $translator->transChoice('foo', 1, [], '', $locale); + // no assertion. this method just asserts that no exception is thrown + $this->addToAssertionCount(1); + } + + /** + * @group legacy + */ + public function testTransChoiceNullLocale() + { + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foofoo'], 'en'); + + $translator->transChoice('foo', 1, [], '', null); + // no assertion. this method just asserts that no exception is thrown + $this->addToAssertionCount(1); + } + + public function testTransNullId() + { + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['foo' => 'foofoo'], 'en'); + + $this->assertSame('', $translator->trans(null)); + + (\Closure::bind(function () use ($translator) { + $this->assertSame([], $translator->catalogues); + }, $this, Translator::class))(); + } + + public function getTransFileTests() + { + return [ + ['csv', 'CsvFileLoader'], + ['ini', 'IniFileLoader'], + ['mo', 'MoFileLoader'], + ['po', 'PoFileLoader'], + ['php', 'PhpFileLoader'], + ['ts', 'QtFileLoader'], + ['xlf', 'XliffFileLoader'], + ['yml', 'YamlFileLoader'], + ['json', 'JsonFileLoader'], + ]; + } + + public function getTransTests() + { + return [ + ['Symfony est super !', 'Symfony is great!', 'Symfony est super !', [], 'fr', ''], + ['Symfony est awesome !', 'Symfony is %what%!', 'Symfony est %what% !', ['%what%' => 'awesome'], 'fr', ''], + ['Symfony est super !', new StringClass('Symfony is great!'), 'Symfony est super !', [], 'fr', ''], + ['', null, '', [], 'fr', ''], + ]; + } + + public function getFlattenedTransTests() + { + $messages = [ + 'symfony' => [ + 'is' => [ + 'great' => 'Symfony est super!', + ], + ], + 'foo' => [ + 'bar' => [ + 'baz' => 'Foo Bar Baz', + ], + 'baz' => 'Foo Baz', + ], + ]; + + return [ + ['Symfony est super!', $messages, 'symfony.is.great'], + ['Foo Bar Baz', $messages, 'foo.bar.baz'], + ['Foo Baz', $messages, 'foo.baz'], + ]; + } + + public function getTransChoiceTests() + { + return [ + ['Il y a 0 pomme', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, [], 'fr', ''], + ['Il y a 1 pomme', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 1, [], 'fr', ''], + ['Il y a 10 pommes', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 10, [], 'fr', ''], + + ['Il y a 0 pomme', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 0, [], 'fr', ''], + ['Il y a 1 pomme', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 1, [], 'fr', ''], + ['Il y a 10 pommes', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 10, [], 'fr', ''], + + ['Il y a 0 pomme', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 0, [], 'fr', ''], + ['Il y a 1 pomme', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 1, [], 'fr', ''], + ['Il y a 10 pommes', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 10, [], 'fr', ''], + + ['Il n\'y a aucune pomme', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 0, [], 'fr', ''], + ['Il y a 1 pomme', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 1, [], 'fr', ''], + ['Il y a 10 pommes', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 10, [], 'fr', ''], + + ['Il y a 0 pomme', new StringClass('{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples'), '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, [], 'fr', ''], + + // Override %count% with a custom value + ['Il y a quelques pommes', 'one: There is one apple|more: There are %count% apples', 'one: Il y a %count% pomme|more: Il y a quelques pommes', 2, ['%count%' => 'quelques'], 'fr', ''], + ]; + } + + public function getInvalidLocalesTests() + { + return [ + ['fr FR'], + ['français'], + ['fr+en'], + ['utf#8'], + ['fr&en'], + ['fr~FR'], + [' fr'], + ['fr '], + ['fr*'], + ['fr/FR'], + ['fr\\FR'], + ]; + } + + public function getValidLocalesTests() + { + return [ + [''], + ['fr'], + ['francais'], + ['FR'], + ['frFR'], + ['fr-FR'], + ['fr_FR'], + ['fr.FR'], + ['fr-FR.UTF8'], + ['sr@latin'], + ]; + } + + /** + * @requires extension intl + */ + public function testIntlFormattedDomain() + { + $translator = new Translator('en'); + $translator->addLoader('array', new ArrayLoader()); + + $translator->addResource('array', ['some_message' => 'Hello %name%'], 'en'); + $this->assertSame('Hello Bob', $translator->trans('some_message', ['%name%' => 'Bob'])); + + $translator->addResource('array', ['some_message' => 'Hi {name}'], 'en', 'messages+intl-icu'); + $this->assertSame('Hi Bob', $translator->trans('some_message', ['%name%' => 'Bob'])); + } + + /** + * @group legacy + */ + public function testTransChoiceFallback() + { + $translator = new Translator('ru'); + $translator->setFallbackLocales(['en']); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['some_message2' => 'one thing|%count% things'], 'en'); + + $this->assertEquals('10 things', $translator->transChoice('some_message2', 10, ['%count%' => 10])); + } + + /** + * @group legacy + */ + public function testTransChoiceFallbackBis() + { + $translator = new Translator('ru'); + $translator->setFallbackLocales(['en_US', 'en']); + $translator->addLoader('array', new ArrayLoader()); + $translator->addResource('array', ['some_message2' => 'one thing|%count% things'], 'en_US'); + + $this->assertEquals('10 things', $translator->transChoice('some_message2', 10, ['%count%' => 10])); + } + + /** + * @group legacy + */ + public function testTransChoiceFallbackWithNoTranslation() + { + $translator = new Translator('ru'); + $translator->setFallbackLocales(['en']); + $translator->addLoader('array', new ArrayLoader()); + + // consistent behavior with Translator::trans(), which returns the string + // unchanged if it can't be found + $this->assertEquals('some_message2', $translator->transChoice('some_message2', 10, ['%count%' => 10])); + } +} + +class StringClass +{ + protected $str; + + public function __construct($str) + { + $this->str = $str; + } + + public function __toString(): string + { + return $this->str; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Util/ArrayConverterTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Util/ArrayConverterTest.php new file mode 100644 index 0000000..b033541 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Util/ArrayConverterTest.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Util; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Util\ArrayConverter; + +class ArrayConverterTest extends TestCase +{ + /** + * @dataProvider messagesData + */ + public function testDump($input, $expectedOutput) + { + $this->assertEquals($expectedOutput, ArrayConverter::expandToTree($input)); + } + + public function messagesData() + { + return [ + [ + // input + [ + 'foo1' => 'bar', + 'foo.bar' => 'value', + ], + // expected output + [ + 'foo1' => 'bar', + 'foo' => ['bar' => 'value'], + ], + ], + [ + // input + [ + 'foo.bar' => 'value1', + 'foo.bar.test' => 'value2', + ], + // expected output + [ + 'foo' => [ + 'bar' => 'value1', + 'bar.test' => 'value2', + ], + ], + ], + [ + // input + [ + 'foo.level2.level3.level4' => 'value1', + 'foo.level2' => 'value2', + 'foo.bar' => 'value3', + ], + // expected output + [ + 'foo' => [ + 'level2' => 'value2', + 'level2.level3.level4' => 'value1', + 'bar' => 'value3', + ], + ], + ], + ]; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Writer/TranslationWriterTest.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Writer/TranslationWriterTest.php new file mode 100644 index 0000000..d3b6754 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/Writer/TranslationWriterTest.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Writer; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Dumper\DumperInterface; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Writer\TranslationWriter; + +class TranslationWriterTest extends TestCase +{ + public function testWrite() + { + $dumper = $this->getMockBuilder('Symfony\Component\Translation\Dumper\DumperInterface')->getMock(); + $dumper + ->expects($this->once()) + ->method('dump'); + + $writer = new TranslationWriter(); + $writer->addDumper('test', $dumper); + $writer->write(new MessageCatalogue('en'), 'test'); + } + + /** + * @group legacy + */ + public function testDisableBackup() + { + $nonBackupDumper = new NonBackupDumper(); + $backupDumper = new BackupDumper(); + + $writer = new TranslationWriter(); + $writer->addDumper('non_backup', $nonBackupDumper); + $writer->addDumper('backup', $backupDumper); + $writer->disableBackup(); + + $this->assertFalse($backupDumper->backup, 'backup can be disabled if setBackup() method does exist'); + } +} + +class NonBackupDumper implements DumperInterface +{ + public function dump(MessageCatalogue $messages, $options = []) + { + } +} + +class BackupDumper implements DumperInterface +{ + public $backup = true; + + public function dump(MessageCatalogue $messages, $options = []) + { + } + + public function setBackup($backup) + { + $this->backup = $backup; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty-translation.mo b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty-translation.mo new file mode 100644 index 0000000..ed01000 Binary files /dev/null and b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty-translation.mo differ diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty-translation.po b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty-translation.po new file mode 100644 index 0000000..ff6f22a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty-translation.po @@ -0,0 +1,3 @@ +msgid "foo" +msgstr "" + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.csv b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.csv new file mode 100644 index 0000000..e69de29 diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.ini b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.ini new file mode 100644 index 0000000..e69de29 diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.json b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.json new file mode 100644 index 0000000..e69de29 diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.mo b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.mo new file mode 100644 index 0000000..e69de29 diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.po b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.po new file mode 100644 index 0000000..e69de29 diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.xlf new file mode 100644 index 0000000..e69de29 diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.yml b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/empty.yml new file mode 100644 index 0000000..e69de29 diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/encoding.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/encoding.xlf new file mode 100644 index 0000000..0a88f92 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/encoding.xlf @@ -0,0 +1,16 @@ + + + + + + foo + bär + bäz + + + bar + föö + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/escaped-id-plurals.po b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/escaped-id-plurals.po new file mode 100644 index 0000000..c412aa2 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/escaped-id-plurals.po @@ -0,0 +1,10 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" + +msgid "escaped \"foo\"" +msgid_plural "escaped \"foos\"" +msgstr[0] "escaped \"bar\"" +msgstr[1] "escaped \"bars\"" diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/escaped-id.po b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/escaped-id.po new file mode 100644 index 0000000..308eadd --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/escaped-id.po @@ -0,0 +1,8 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" + +msgid "escaped \"foo\"" +msgstr "escaped \"bar\"" diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/extractor/resource.format.engine b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/extractor/resource.format.engine new file mode 100644 index 0000000..e69de29 diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/extractor/this.is.a.template.format.engine b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/extractor/this.is.a.template.format.engine new file mode 100644 index 0000000..e69de29 diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/extractor/translation.html.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/extractor/translation.html.php new file mode 100644 index 0000000..5085eab --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/extractor/translation.html.php @@ -0,0 +1,59 @@ +This template is used for translation message extraction tests +trans('single-quoted key'); ?> +trans('double-quoted key'); ?> +trans(<< +trans(<<<'EOF' +nowdoc key +EOF +); ?> +trans( + "double-quoted key with whitespace and escaped \$\n\" sequences" +); ?> +trans( + 'single-quoted key with whitespace and nonescaped \$\n\' sequences' +); ?> +trans(<< +trans(<<<'EOF' +nowdoc key with whitespace and nonescaped \$\n sequences +EOF +); ?> + +trans('single-quoted key with "quote mark at the end"'); ?> + +transChoice( + '{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples', + 10, + ['%count%' => 10] +); ?> + +trans('concatenated'.' message'.<< + +trans('other-domain-test-no-params-short-array', [], 'not_messages'); ?> + +trans('other-domain-test-no-params-long-array', [], 'not_messages'); ?> + +trans('other-domain-test-params-short-array', ['foo' => 'bar'], 'not_messages'); ?> + +trans('other-domain-test-params-long-array', ['foo' => 'bar'], 'not_messages'); ?> + +transChoice('other-domain-test-trans-choice-short-array-%count%', 10, ['%count%' => 10], 'not_messages'); ?> + +transChoice('other-domain-test-trans-choice-long-array-%count%', 10, ['%count%' => 10], 'not_messages'); ?> + +trans('typecast', ['a' => (int) '123'], 'not_messages'); ?> +transChoice('msg1', 10 + 1, [], 'not_messages'); ?> +transChoice('msg2', ceil(4.5), [], 'not_messages'); ?> + +trans('default domain', [], null); ?> diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/fuzzy-translations.po b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/fuzzy-translations.po new file mode 100644 index 0000000..04d4047 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/fuzzy-translations.po @@ -0,0 +1,10 @@ +#, php-format +msgid "foo1" +msgstr "bar1" + +#, fuzzy, php-format +msgid "foo2" +msgstr "fuzzy bar2" + +msgid "foo3" +msgstr "bar3" diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/invalid-xml-resources.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/invalid-xml-resources.xlf new file mode 100644 index 0000000..7bf6c98 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/invalid-xml-resources.xlf @@ -0,0 +1,23 @@ + + + + + + foo + bar + + + extra + + + key + + + + test + with + note + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/malformed.json b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/malformed.json new file mode 100644 index 0000000..4563ec6 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/malformed.json @@ -0,0 +1,3 @@ +{ + "foo" "bar" +} \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/messages.yml b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/messages.yml new file mode 100644 index 0000000..d4f82d7 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/messages.yml @@ -0,0 +1,3 @@ +foo: + bar1: value1 + bar2: value2 diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/messages_linear.yml b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/messages_linear.yml new file mode 100644 index 0000000..6c1687d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/messages_linear.yml @@ -0,0 +1,2 @@ +foo.bar1: value1 +foo.bar2: value2 diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/missing-plurals.po b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/missing-plurals.po new file mode 100644 index 0000000..3b47fca --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/missing-plurals.po @@ -0,0 +1,4 @@ +msgid "foo" +msgid_plural "foos" +msgstr[3] "bars" +msgstr[1] "bar" diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/non-valid.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/non-valid.xlf new file mode 100644 index 0000000..734fc97 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/non-valid.xlf @@ -0,0 +1,11 @@ + + + + + + foo + bar + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/non-valid.yml b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/non-valid.yml new file mode 100644 index 0000000..257cc56 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/non-valid.yml @@ -0,0 +1 @@ +foo diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/plurals.mo b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/plurals.mo new file mode 100644 index 0000000..3945ad9 Binary files /dev/null and b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/plurals.mo differ diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/plurals.po b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/plurals.po new file mode 100644 index 0000000..5d7b39d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/plurals.po @@ -0,0 +1,13 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" + +msgid "foo" +msgid_plural "foos" +msgstr[0] "bar" +msgstr[1] "bars" + +msgid "{0} no foos|one foo|%count% foos" +msgstr "{0} no bars|one bar|%count% bars" diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resname.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resname.xlf new file mode 100644 index 0000000..4fa5c00 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resname.xlf @@ -0,0 +1,22 @@ + + + + + + + bar + + + bar source + baz + + + baz + foo + + + qux source + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/corrupted/resources.dat b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/corrupted/resources.dat new file mode 100644 index 0000000..391250c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/corrupted/resources.dat @@ -0,0 +1 @@ +XXX \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.res b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.res new file mode 100644 index 0000000..1fc1436 Binary files /dev/null and b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.res differ diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.txt b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.txt new file mode 100644 index 0000000..3d9e9ea --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/en.txt @@ -0,0 +1,3 @@ +en{ + symfony{"Symfony is great"} +} \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.res b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.res new file mode 100644 index 0000000..f584160 Binary files /dev/null and b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.res differ diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.txt b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.txt new file mode 100644 index 0000000..182d0a0 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/fr.txt @@ -0,0 +1,3 @@ +fr{ + symfony{"Symfony est génial"} +} \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/packagelist.txt b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/packagelist.txt new file mode 100644 index 0000000..c5783ed --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/packagelist.txt @@ -0,0 +1,2 @@ +en.res +fr.res diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/resources.dat b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/resources.dat new file mode 100644 index 0000000..563b0ea Binary files /dev/null and b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/resources.dat differ diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/res/en.res b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/res/en.res new file mode 100644 index 0000000..ad894a9 Binary files /dev/null and b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resourcebundle/res/en.res differ diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0+intl-icu.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0+intl-icu.xlf new file mode 100644 index 0000000..6294f16 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0+intl-icu.xlf @@ -0,0 +1,11 @@ + + + + + + foo + bar + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0-clean.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0-clean.xlf new file mode 100644 index 0000000..efa69b2 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0-clean.xlf @@ -0,0 +1,23 @@ + + + + + + foo + bar + + + + + key + + + + + + key.with.cdata + & ]]> + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0-multi-segment-unit.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0-multi-segment-unit.xlf new file mode 100644 index 0000000..d0dc2a8 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0-multi-segment-unit.xlf @@ -0,0 +1,17 @@ + + + + + true + + + foo + foo (translated) + + + bar + bar (translated) + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0.xlf new file mode 100644 index 0000000..166172a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-2.0.xlf @@ -0,0 +1,25 @@ + + + + + + Quetzal + Quetzal + + + + + + foo + XLIFF 文書を編集ã€ã¾ãŸã¯å‡¦ç† ã™ã‚‹ã‚¢ãƒ—リケーションã§ã™ã€‚ + + + + + bar + XLIFF データ・マãƒãƒ¼ã‚¸ãƒ£ + + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-clean.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-clean.xlf new file mode 100644 index 0000000..00c8a5c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-clean.xlf @@ -0,0 +1,25 @@ + + + +
+ +
+ + + foo + bar + baz + + + key + + baz + qux + + + key.with.cdata + & ]]> + + +
+
diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-multi-files.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-multi-files.xlf new file mode 100644 index 0000000..5f45150 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-multi-files.xlf @@ -0,0 +1,27 @@ + + + + + + foo + bar + + + + + + + extra + + + key + + + + test + with + note + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-notes-meta.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-notes-meta.xlf new file mode 100644 index 0000000..7d5bbd4 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-notes-meta.xlf @@ -0,0 +1,26 @@ + + + + + + new + true + user login + + + foo + bar + + + + + x_content + Fuzzy + + + baz + biz + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-target-attributes.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-target-attributes.xlf new file mode 100644 index 0000000..700d281 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-target-attributes.xlf @@ -0,0 +1,14 @@ + + + +
+ +
+ + + foo + bar + + +
+
diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-tool-info.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-tool-info.xlf new file mode 100644 index 0000000..1c2ae95 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources-tool-info.xlf @@ -0,0 +1,14 @@ + + + +
+ +
+ + + foo + bar + + +
+
diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.csv b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.csv new file mode 100644 index 0000000..374b9eb --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.csv @@ -0,0 +1,4 @@ +"foo"; "bar" +#"bar"; "foo" +"incorrect"; "number"; "columns"; "will"; "be"; "ignored" +"incorrect" \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.dump.json b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.dump.json new file mode 100644 index 0000000..335965d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.dump.json @@ -0,0 +1 @@ +{"foo":"\u0022bar\u0022"} \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.ini b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.ini new file mode 100644 index 0000000..4953062 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.ini @@ -0,0 +1 @@ +foo="bar" diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.json b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.json new file mode 100644 index 0000000..8a79687 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.json @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} \ No newline at end of file diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.mo b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.mo new file mode 100644 index 0000000..0a96602 Binary files /dev/null and b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.mo differ diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.php new file mode 100644 index 0000000..c291398 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.php @@ -0,0 +1,5 @@ + 'bar', +); diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.po b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.po new file mode 100644 index 0000000..68e0f2d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.po @@ -0,0 +1,24 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" + +msgid "foo" +msgstr "bar" + +msgid "bar" +msgstr "foo" + +# Comment 1 +# Comment 2 +#, fuzzy,another +#: src/file_1 src/file_2:50 +msgid "foo_bar" +msgstr "foobar" + +# Comment +#, fuzzy +#: src/file_1 +msgid "bar_foo" +msgstr "barfoo" diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.ts b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.ts new file mode 100644 index 0000000..29e6a6f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.ts @@ -0,0 +1,21 @@ + + + + resources + + foo + bar + + + + + foo_bar + foobar + + + + bar_foo + barfoo + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.xlf new file mode 100644 index 0000000..b0e5988 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.xlf @@ -0,0 +1,23 @@ + + + + + + foo + bar + + + extra + + + key + + + + test + with + note + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.yml b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.yml new file mode 100644 index 0000000..20e9ff3 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/resources.yml @@ -0,0 +1 @@ +foo: bar diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/valid.csv b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/valid.csv new file mode 100644 index 0000000..59882e5 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/valid.csv @@ -0,0 +1,4 @@ +foo;bar +bar;"foo +foo" +"foo;foo";bar diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/with-attributes.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/with-attributes.xlf new file mode 100644 index 0000000..7873062 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/with-attributes.xlf @@ -0,0 +1,21 @@ + + + + + + foo + bar + + + extra + bar + + + key + + baz + qux + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/withdoctype.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/withdoctype.xlf new file mode 100644 index 0000000..f83e834 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/withdoctype.xlf @@ -0,0 +1,12 @@ + + + + + + + foo + bar + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/withnote.xlf b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/withnote.xlf new file mode 100644 index 0000000..f98cf7f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Tests/fixtures/withnote.xlf @@ -0,0 +1,22 @@ + + + + + + foo + bar + foo + + + extrasource + bar + + + key + + baz + qux + + + + diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Translator.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Translator.php new file mode 100644 index 0000000..9876051 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Translator.php @@ -0,0 +1,540 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\Config\ConfigCacheFactory; +use Symfony\Component\Config\ConfigCacheFactoryInterface; +use Symfony\Component\Config\ConfigCacheInterface; +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\LogicException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\Exception\RuntimeException; +use Symfony\Component\Translation\Formatter\ChoiceMessageFormatterInterface; +use Symfony\Component\Translation\Formatter\IntlFormatterInterface; +use Symfony\Component\Translation\Formatter\MessageFormatter; +use Symfony\Component\Translation\Formatter\MessageFormatterInterface; +use Symfony\Component\Translation\Loader\LoaderInterface; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * @author Fabien Potencier + */ +class Translator implements LegacyTranslatorInterface, TranslatorInterface, TranslatorBagInterface +{ + /** + * @var MessageCatalogueInterface[] + */ + protected $catalogues = []; + + /** + * @var string + */ + private $locale; + + /** + * @var array + */ + private $fallbackLocales = []; + + /** + * @var LoaderInterface[] + */ + private $loaders = []; + + /** + * @var array + */ + private $resources = []; + + /** + * @var MessageFormatterInterface + */ + private $formatter; + + /** + * @var string + */ + private $cacheDir; + + /** + * @var bool + */ + private $debug; + + private $cacheVary; + + /** + * @var ConfigCacheFactoryInterface|null + */ + private $configCacheFactory; + + /** + * @var array|null + */ + private $parentLocales; + + private $hasIntlFormatter; + + /** + * @throws InvalidArgumentException If a locale contains invalid characters + */ + public function __construct(?string $locale, MessageFormatterInterface $formatter = null, string $cacheDir = null, bool $debug = false, array $cacheVary = []) + { + if (null === $locale) { + @trigger_error(sprintf('Passing "null" as the $locale argument to %s() is deprecated since Symfony 4.4.', __METHOD__), E_USER_DEPRECATED); + } + + $this->setLocale($locale, false); + + if (null === $formatter) { + $formatter = new MessageFormatter(); + } + + $this->formatter = $formatter; + $this->cacheDir = $cacheDir; + $this->debug = $debug; + $this->cacheVary = $cacheVary; + $this->hasIntlFormatter = $formatter instanceof IntlFormatterInterface; + } + + public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory) + { + $this->configCacheFactory = $configCacheFactory; + } + + /** + * Adds a Loader. + * + * @param string $format The name of the loader (@see addResource()) + */ + public function addLoader($format, LoaderInterface $loader) + { + $this->loaders[$format] = $loader; + } + + /** + * Adds a Resource. + * + * @param string $format The name of the loader (@see addLoader()) + * @param mixed $resource The resource name + * @param string $locale The locale + * @param string $domain The domain + * + * @throws InvalidArgumentException If the locale contains invalid characters + */ + public function addResource($format, $resource, $locale, $domain = null) + { + if (null === $domain) { + $domain = 'messages'; + } + + if (null === $locale) { + @trigger_error(sprintf('Passing "null" to the third argument of the "%s" method has been deprecated since Symfony 4.4 and will throw an error in 5.0.', __METHOD__), E_USER_DEPRECATED); + } + + $this->assertValidLocale($locale); + + $this->resources[$locale][] = [$format, $resource, $domain]; + + if (\in_array($locale, $this->fallbackLocales)) { + $this->catalogues = []; + } else { + unset($this->catalogues[$locale]); + } + } + + /** + * {@inheritdoc} + */ + public function setLocale($locale) + { + if (null === $locale && (2 > \func_num_args() || func_get_arg(1))) { + @trigger_error(sprintf('Passing "null" as the $locale argument to %s() is deprecated since Symfony 4.4.', __METHOD__), E_USER_DEPRECATED); + } + + $this->assertValidLocale($locale); + $this->locale = $locale; + } + + /** + * {@inheritdoc} + */ + public function getLocale() + { + return $this->locale; + } + + /** + * Sets the fallback locales. + * + * @param array $locales The fallback locales + * + * @throws InvalidArgumentException If a locale contains invalid characters + */ + public function setFallbackLocales(array $locales) + { + // needed as the fallback locales are linked to the already loaded catalogues + $this->catalogues = []; + + foreach ($locales as $locale) { + if (null === $locale) { + @trigger_error(sprintf('Passing "null" as the $locale argument to %s() is deprecated since Symfony 4.4.', __METHOD__), E_USER_DEPRECATED); + } + $this->assertValidLocale($locale); + } + + $this->fallbackLocales = $this->cacheVary['fallback_locales'] = $locales; + } + + /** + * Gets the fallback locales. + * + * @internal since Symfony 4.2 + * + * @return array The fallback locales + */ + public function getFallbackLocales() + { + return $this->fallbackLocales; + } + + /** + * {@inheritdoc} + */ + public function trans($id, array $parameters = [], $domain = null, $locale = null) + { + if ('' === $id = (string) $id) { + return ''; + } + + if (null === $domain) { + $domain = 'messages'; + } + + $catalogue = $this->getCatalogue($locale); + $locale = $catalogue->getLocale(); + while (!$catalogue->defines($id, $domain)) { + if ($cat = $catalogue->getFallbackCatalogue()) { + $catalogue = $cat; + $locale = $catalogue->getLocale(); + } else { + break; + } + } + + if ($this->hasIntlFormatter && $catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) { + return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, $parameters); + } + + return $this->formatter->format($catalogue->get($id, $domain), $locale, $parameters); + } + + /** + * {@inheritdoc} + * + * @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter + */ + public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null) + { + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%%count%%" parameter.', __METHOD__), E_USER_DEPRECATED); + + if ('' === $id = (string) $id) { + return ''; + } + + if (!$this->formatter instanceof ChoiceMessageFormatterInterface) { + throw new LogicException(sprintf('The formatter "%s" does not support plural translations.', \get_class($this->formatter))); + } + + if (null === $domain) { + $domain = 'messages'; + } + + $catalogue = $this->getCatalogue($locale); + $locale = $catalogue->getLocale(); + while (!$catalogue->defines($id, $domain)) { + if ($cat = $catalogue->getFallbackCatalogue()) { + $catalogue = $cat; + $locale = $catalogue->getLocale(); + } else { + break; + } + } + + if ($this->hasIntlFormatter && $catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) { + return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, ['%count%' => $number] + $parameters); + } + + return $this->formatter->choiceFormat($catalogue->get($id, $domain), $number, $locale, $parameters); + } + + /** + * {@inheritdoc} + */ + public function getCatalogue($locale = null) + { + if (null === $locale) { + $locale = $this->getLocale(); + } else { + $this->assertValidLocale($locale); + } + + if (!isset($this->catalogues[$locale])) { + $this->loadCatalogue($locale); + } + + return $this->catalogues[$locale]; + } + + /** + * Gets the loaders. + * + * @return array LoaderInterface[] + */ + protected function getLoaders() + { + return $this->loaders; + } + + /** + * @param string $locale + */ + protected function loadCatalogue($locale) + { + if (null === $this->cacheDir) { + $this->initializeCatalogue($locale); + } else { + $this->initializeCacheCatalogue($locale); + } + } + + /** + * @param string $locale + */ + protected function initializeCatalogue($locale) + { + $this->assertValidLocale($locale); + + try { + $this->doLoadCatalogue($locale); + } catch (NotFoundResourceException $e) { + if (!$this->computeFallbackLocales($locale)) { + throw $e; + } + } + $this->loadFallbackCatalogues($locale); + } + + private function initializeCacheCatalogue(string $locale): void + { + if (isset($this->catalogues[$locale])) { + /* Catalogue already initialized. */ + return; + } + + $this->assertValidLocale($locale); + $cache = $this->getConfigCacheFactory()->cache($this->getCatalogueCachePath($locale), + function (ConfigCacheInterface $cache) use ($locale) { + $this->dumpCatalogue($locale, $cache); + } + ); + + if (isset($this->catalogues[$locale])) { + /* Catalogue has been initialized as it was written out to cache. */ + return; + } + + /* Read catalogue from cache. */ + $this->catalogues[$locale] = include $cache->getPath(); + } + + private function dumpCatalogue(string $locale, ConfigCacheInterface $cache): void + { + $this->initializeCatalogue($locale); + $fallbackContent = $this->getFallbackContent($this->catalogues[$locale]); + + $content = sprintf(<<getAllMessages($this->catalogues[$locale]), true), + $fallbackContent + ); + + $cache->write($content, $this->catalogues[$locale]->getResources()); + } + + private function getFallbackContent(MessageCatalogue $catalogue): string + { + $fallbackContent = ''; + $current = ''; + $replacementPattern = '/[^a-z0-9_]/i'; + $fallbackCatalogue = $catalogue->getFallbackCatalogue(); + while ($fallbackCatalogue) { + $fallback = $fallbackCatalogue->getLocale(); + $fallbackSuffix = ucfirst(preg_replace($replacementPattern, '_', $fallback)); + $currentSuffix = ucfirst(preg_replace($replacementPattern, '_', $current)); + + $fallbackContent .= sprintf(<<<'EOF' +$catalogue%s = new MessageCatalogue('%s', %s); +$catalogue%s->addFallbackCatalogue($catalogue%s); + +EOF + , + $fallbackSuffix, + $fallback, + var_export($this->getAllMessages($fallbackCatalogue), true), + $currentSuffix, + $fallbackSuffix + ); + $current = $fallbackCatalogue->getLocale(); + $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue(); + } + + return $fallbackContent; + } + + private function getCatalogueCachePath(string $locale): string + { + return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('sha256', serialize($this->cacheVary), true)), 0, 7), '/', '_').'.php'; + } + + /** + * @internal + */ + protected function doLoadCatalogue(string $locale): void + { + $this->catalogues[$locale] = new MessageCatalogue($locale); + + if (isset($this->resources[$locale])) { + foreach ($this->resources[$locale] as $resource) { + if (!isset($this->loaders[$resource[0]])) { + throw new RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0])); + } + $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2])); + } + } + } + + private function loadFallbackCatalogues(string $locale): void + { + $current = $this->catalogues[$locale]; + + foreach ($this->computeFallbackLocales($locale) as $fallback) { + if (!isset($this->catalogues[$fallback])) { + $this->initializeCatalogue($fallback); + } + + $fallbackCatalogue = new MessageCatalogue($fallback, $this->getAllMessages($this->catalogues[$fallback])); + foreach ($this->catalogues[$fallback]->getResources() as $resource) { + $fallbackCatalogue->addResource($resource); + } + $current->addFallbackCatalogue($fallbackCatalogue); + $current = $fallbackCatalogue; + } + } + + protected function computeFallbackLocales($locale) + { + if (null === $this->parentLocales) { + $parentLocales = json_decode(file_get_contents(__DIR__.'/Resources/data/parents.json'), true); + } + + $locales = []; + foreach ($this->fallbackLocales as $fallback) { + if ($fallback === $locale) { + continue; + } + + $locales[] = $fallback; + } + + while ($locale) { + $parent = $parentLocales[$locale] ?? null; + + if ($parent) { + $locale = 'root' !== $parent ? $parent : null; + } elseif (\function_exists('locale_parse')) { + $localeSubTags = locale_parse($locale); + $locale = null; + if (1 < \count($localeSubTags)) { + array_pop($localeSubTags); + $locale = locale_compose($localeSubTags) ?: null; + } + } elseif ($i = strrpos($locale, '_') ?: strrpos($locale, '-')) { + $locale = substr($locale, 0, $i); + } else { + $locale = null; + } + + if (null !== $locale) { + array_unshift($locales, $locale); + } + } + + return array_unique($locales); + } + + /** + * Asserts that the locale is valid, throws an Exception if not. + * + * @param string $locale Locale to tests + * + * @throws InvalidArgumentException If the locale contains invalid characters + */ + protected function assertValidLocale($locale) + { + if (1 !== preg_match('/^[a-z0-9@_\\.\\-]*$/i', $locale)) { + throw new InvalidArgumentException(sprintf('Invalid "%s" locale.', $locale)); + } + } + + /** + * Provides the ConfigCache factory implementation, falling back to a + * default implementation if necessary. + */ + private function getConfigCacheFactory(): ConfigCacheFactoryInterface + { + if (!$this->configCacheFactory) { + $this->configCacheFactory = new ConfigCacheFactory($this->debug); + } + + return $this->configCacheFactory; + } + + private function getAllMessages(MessageCatalogueInterface $catalogue): array + { + $allMessages = []; + + foreach ($catalogue->all() as $domain => $messages) { + if ($intlMessages = $catalogue->all($domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) { + $allMessages[$domain.MessageCatalogue::INTL_DOMAIN_SUFFIX] = $intlMessages; + $messages = array_diff_key($messages, $intlMessages); + } + if ($messages) { + $allMessages[$domain] = $messages; + } + } + + return $allMessages; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/TranslatorBagInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/TranslatorBagInterface.php new file mode 100644 index 0000000..5e49e2d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/TranslatorBagInterface.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; + +/** + * TranslatorBagInterface. + * + * @author Abdellatif Ait boudad + */ +interface TranslatorBagInterface +{ + /** + * Gets the catalogue by locale. + * + * @param string|null $locale The locale or null to use the default + * + * @return MessageCatalogueInterface + * + * @throws InvalidArgumentException If the locale contains invalid characters + */ + public function getCatalogue($locale = null); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/TranslatorInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/TranslatorInterface.php new file mode 100644 index 0000000..f677d24 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/TranslatorInterface.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Contracts\Translation\LocaleAwareInterface; + +/** + * TranslatorInterface. + * + * @author Fabien Potencier + * + * @deprecated since Symfony 4.2, use Symfony\Contracts\Translation\TranslatorInterface instead + */ +interface TranslatorInterface extends LocaleAwareInterface +{ + /** + * Translates the given message. + * + * @param string $id The message id (may also be an object that can be cast to string) + * @param array $parameters An array of parameters for the message + * @param string|null $domain The domain for the message or null to use the default + * @param string|null $locale The locale or null to use the default + * + * @return string The translated string + * + * @throws InvalidArgumentException If the locale contains invalid characters + */ + public function trans($id, array $parameters = [], $domain = null, $locale = null); + + /** + * Translates the given choice message by choosing a translation according to a number. + * + * @param string $id The message id (may also be an object that can be cast to string) + * @param int $number The number to use to find the index of the message + * @param array $parameters An array of parameters for the message + * @param string|null $domain The domain for the message or null to use the default + * @param string|null $locale The locale or null to use the default + * + * @return string The translated string + * + * @throws InvalidArgumentException If the locale contains invalid characters + */ + public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null); + + /** + * Sets the current locale. + * + * @param string $locale The locale + * + * @throws InvalidArgumentException If the locale contains invalid characters + */ + public function setLocale($locale); + + /** + * Returns the current locale. + * + * @return string The locale + */ + public function getLocale(); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Util/ArrayConverter.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Util/ArrayConverter.php new file mode 100644 index 0000000..22c602e --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Util/ArrayConverter.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Util; + +/** + * ArrayConverter generates tree like structure from a message catalogue. + * e.g. this + * 'foo.bar1' => 'test1', + * 'foo.bar2' => 'test2' + * converts to follows: + * foo: + * bar1: test1 + * bar2: test2. + * + * @author Gennady Telegin + */ +class ArrayConverter +{ + /** + * Converts linear messages array to tree-like array. + * For example this array('foo.bar' => 'value') will be converted to ['foo' => ['bar' => 'value']]. + * + * @param array $messages Linear messages array + * + * @return array Tree-like messages array + */ + public static function expandToTree(array $messages) + { + $tree = []; + + foreach ($messages as $id => $value) { + $referenceToElement = &self::getElementByPath($tree, explode('.', $id)); + + $referenceToElement = $value; + + unset($referenceToElement); + } + + return $tree; + } + + private static function &getElementByPath(array &$tree, array $parts) + { + $elem = &$tree; + $parentOfElem = null; + + foreach ($parts as $i => $part) { + if (isset($elem[$part]) && \is_string($elem[$part])) { + /* Process next case: + * 'foo': 'test1', + * 'foo.bar': 'test2' + * + * $tree['foo'] was string before we found array {bar: test2}. + * Treat new element as string too, e.g. add $tree['foo.bar'] = 'test2'; + */ + $elem = &$elem[implode('.', \array_slice($parts, $i))]; + break; + } + $parentOfElem = &$elem; + $elem = &$elem[$part]; + } + + if ($elem && \is_array($elem) && $parentOfElem) { + /* Process next case: + * 'foo.bar': 'test1' + * 'foo': 'test2' + * + * $tree['foo'] was array = {bar: 'test1'} before we found string constant `foo`. + * Cancel treating $tree['foo'] as array and cancel back it expansion, + * e.g. make it $tree['foo.bar'] = 'test1' again. + */ + self::cancelExpand($parentOfElem, $part, $elem); + } + + return $elem; + } + + private static function cancelExpand(array &$tree, $prefix, array $node) + { + $prefix .= '.'; + + foreach ($node as $id => $value) { + if (\is_string($value)) { + $tree[$prefix.$id] = $value; + } else { + self::cancelExpand($tree, $prefix.$id, $value); + } + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Util/XliffUtils.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Util/XliffUtils.php new file mode 100644 index 0000000..b5ff4ef --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Util/XliffUtils.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Util; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\InvalidResourceException; + +/** + * Provides some utility methods for XLIFF translation files, such as validating + * their contents according to the XSD schema. + * + * @author Fabien Potencier + */ +class XliffUtils +{ + /** + * Gets xliff file version based on the root "version" attribute. + * + * Defaults to 1.2 for backwards compatibility. + * + * @throws InvalidArgumentException + */ + public static function getVersionNumber(\DOMDocument $dom): string + { + /** @var \DOMNode $xliff */ + foreach ($dom->getElementsByTagName('xliff') as $xliff) { + $version = $xliff->attributes->getNamedItem('version'); + if ($version) { + return $version->nodeValue; + } + + $namespace = $xliff->attributes->getNamedItem('xmlns'); + if ($namespace) { + if (0 !== substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34)) { + throw new InvalidArgumentException(sprintf('Not a valid XLIFF namespace "%s".', $namespace)); + } + + return substr($namespace, 34); + } + } + + // Falls back to v1.2 + return '1.2'; + } + + /** + * Validates and parses the given file into a DOMDocument. + * + * @throws InvalidResourceException + */ + public static function validateSchema(\DOMDocument $dom): array + { + $xliffVersion = static::getVersionNumber($dom); + $internalErrors = libxml_use_internal_errors(true); + $disableEntities = libxml_disable_entity_loader(false); + + $isValid = @$dom->schemaValidateSource(self::getSchema($xliffVersion)); + if (!$isValid) { + libxml_disable_entity_loader($disableEntities); + + return self::getXmlErrors($internalErrors); + } + + libxml_disable_entity_loader($disableEntities); + + $dom->normalizeDocument(); + + libxml_clear_errors(); + libxml_use_internal_errors($internalErrors); + + return []; + } + + public static function getErrorsAsString(array $xmlErrors): string + { + $errorsAsString = ''; + + foreach ($xmlErrors as $error) { + $errorsAsString .= sprintf("[%s %s] %s (in %s - line %d, column %d)\n", + LIBXML_ERR_WARNING === $error['level'] ? 'WARNING' : 'ERROR', + $error['code'], + $error['message'], + $error['file'], + $error['line'], + $error['column'] + ); + } + + return $errorsAsString; + } + + private static function getSchema(string $xliffVersion): string + { + if ('1.2' === $xliffVersion) { + $schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-1.2-strict.xsd'); + $xmlUri = 'http://www.w3.org/2001/xml.xsd'; + } elseif ('2.0' === $xliffVersion) { + $schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-2.0.xsd'); + $xmlUri = 'informativeCopiesOf3rdPartySchemas/w3c/xml.xsd'; + } else { + throw new InvalidArgumentException(sprintf('No support implemented for loading XLIFF version "%s".', $xliffVersion)); + } + + return self::fixXmlLocation($schemaSource, $xmlUri); + } + + /** + * Internally changes the URI of a dependent xsd to be loaded locally. + */ + private static function fixXmlLocation(string $schemaSource, string $xmlUri): string + { + $newPath = str_replace('\\', '/', __DIR__).'/../Resources/schemas/xml.xsd'; + $parts = explode('/', $newPath); + $locationstart = 'file:///'; + if (0 === stripos($newPath, 'phar://')) { + $tmpfile = tempnam(sys_get_temp_dir(), 'symfony'); + if ($tmpfile) { + copy($newPath, $tmpfile); + $parts = explode('/', str_replace('\\', '/', $tmpfile)); + } else { + array_shift($parts); + $locationstart = 'phar:///'; + } + } + + $drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; + $newPath = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts)); + + return str_replace($xmlUri, $newPath, $schemaSource); + } + + /** + * Returns the XML errors of the internal XML parser. + */ + private static function getXmlErrors(bool $internalErrors): array + { + $errors = []; + foreach (libxml_get_errors() as $error) { + $errors[] = [ + 'level' => LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', + 'code' => $error->code, + 'message' => trim($error->message), + 'file' => $error->file ?: 'n/a', + 'line' => $error->line, + 'column' => $error->column, + ]; + } + + libxml_clear_errors(); + libxml_use_internal_errors($internalErrors); + + return $errors; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Writer/TranslationWriter.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Writer/TranslationWriter.php new file mode 100644 index 0000000..a981b8d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Writer/TranslationWriter.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Writer; + +use Symfony\Component\Translation\Dumper\DumperInterface; +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\RuntimeException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * TranslationWriter writes translation messages. + * + * @author Michel Salib + */ +class TranslationWriter implements TranslationWriterInterface +{ + private $dumpers = []; + + /** + * Adds a dumper to the writer. + * + * @param string $format The format of the dumper + */ + public function addDumper($format, DumperInterface $dumper) + { + $this->dumpers[$format] = $dumper; + } + + /** + * Disables dumper backup. + * + * @deprecated since Symfony 4.1 + */ + public function disableBackup() + { + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1.', __METHOD__), E_USER_DEPRECATED); + + foreach ($this->dumpers as $dumper) { + if (method_exists($dumper, 'setBackup')) { + $dumper->setBackup(false); + } + } + } + + /** + * Obtains the list of supported formats. + * + * @return array + */ + public function getFormats() + { + return array_keys($this->dumpers); + } + + /** + * Writes translation from the catalogue according to the selected format. + * + * @param string $format The format to use to dump the messages + * @param array $options Options that are passed to the dumper + * + * @throws InvalidArgumentException + */ + public function write(MessageCatalogue $catalogue, $format, $options = []) + { + if (!isset($this->dumpers[$format])) { + throw new InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format)); + } + + // get the right dumper + $dumper = $this->dumpers[$format]; + + if (isset($options['path']) && !is_dir($options['path']) && !@mkdir($options['path'], 0777, true) && !is_dir($options['path'])) { + throw new RuntimeException(sprintf('Translation Writer was not able to create directory "%s".', $options['path'])); + } + + // save + $dumper->dump($catalogue, $options); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/Writer/TranslationWriterInterface.php b/plugins/vdomah/jwtauth/vendor/symfony/translation/Writer/TranslationWriterInterface.php new file mode 100644 index 0000000..f7c56be --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/Writer/TranslationWriterInterface.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Writer; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * TranslationWriter writes translation messages. + * + * @author Michel Salib + */ +interface TranslationWriterInterface +{ + /** + * Writes translation from the catalogue according to the selected format. + * + * @param string $format The format to use to dump the messages + * @param array $options Options that are passed to the dumper + * + * @throws InvalidArgumentException + */ + public function write(MessageCatalogue $catalogue, $format, $options = []); +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/composer.json b/plugins/vdomah/jwtauth/vendor/symfony/translation/composer.json new file mode 100644 index 0000000..5b01b6d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/composer.json @@ -0,0 +1,60 @@ +{ + "name": "symfony/translation", + "type": "library", + "description": "Symfony Translation Component", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^1.1.6|^2" + }, + "require-dev": { + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/console": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/http-kernel": "^4.4", + "symfony/intl": "^3.4|^4.0|^5.0", + "symfony/service-contracts": "^1.1.2|^2", + "symfony/yaml": "^3.4|^4.0|^5.0", + "symfony/finder": "~2.8|~3.0|~4.0|^5.0", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/config": "<3.4", + "symfony/dependency-injection": "<3.4", + "symfony/http-kernel": "<4.4", + "symfony/yaml": "<3.4" + }, + "provide": { + "symfony/translation-implementation": "1.0" + }, + "suggest": { + "symfony/config": "", + "symfony/yaml": "", + "psr/log-implementation": "To use logging capability in translator" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Translation\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/symfony/translation/phpunit.xml.dist b/plugins/vdomah/jwtauth/vendor/symfony/translation/phpunit.xml.dist new file mode 100644 index 0000000..21d3246 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/symfony/translation/phpunit.xml.dist @@ -0,0 +1,30 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Tests + ./vendor + + + + diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/LICENSE b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/LICENSE new file mode 100644 index 0000000..72a2739 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Sean Tymon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/README.md b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/README.md new file mode 100644 index 0000000..dcf76e0 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/README.md @@ -0,0 +1,40 @@ +# jwt-auth + +> JSON Web Token Authentication for Laravel + +[![Build Status](http://img.shields.io/travis/tymondesigns/jwt-auth/master.svg?style=flat-square)](https://travis-ci.org/tymondesigns/jwt-auth) +[![Scrutinizer Code Quality](http://img.shields.io/scrutinizer/g/tymondesigns/jwt-auth.svg?style=flat-square)](https://scrutinizer-ci.com/g/tymondesigns/jwt-auth/) +[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/tymondesigns/jwt-auth.svg?style=flat-square)](https://scrutinizer-ci.com/g/tymondesigns/jwt-auth/code-structure) +[![StyleCI](https://styleci.io/repos/23680678/shield?style=flat-square)](https://styleci.io/repos/23680678) +[![HHVM](https://img.shields.io/hhvm/tymon/jwt-auth.svg?style=flat-square)](http://hhvm.h4cc.de/package/tymon/jwt-auth) +[![Latest Version](http://img.shields.io/packagist/v/tymon/jwt-auth.svg?style=flat-square)](https://packagist.org/packages/tymon/jwt-auth) +[![Latest Dev Version](https://img.shields.io/packagist/vpre/tymon/jwt-auth.svg?style=flat-square)](https://packagist.org/packages/tymon/jwt-auth#dev-develop) +[![Monthly Downloads](https://img.shields.io/packagist/dm/tymon/jwt-auth.svg?style=flat-square)](https://packagist.org/packages/tymon/jwt-auth) + +See the [WIKI](https://github.com/tymondesigns/jwt-auth/wiki) for documentation + +## License + +The MIT License (MIT) + +Copyright (c) 2014 Sean Tymon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +[![Gratipay](https://img.shields.io/gratipay/tymondesigns.svg?style=flat-square)](https://gratipay.com/~tymondesigns) diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/composer.json b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/composer.json new file mode 100644 index 0000000..1faf3a6 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/composer.json @@ -0,0 +1,51 @@ +{ + "name": "tymon/jwt-auth", + "description": "JSON Web Token Authentication for Laravel 4 and 5", + "keywords": [ + "jwt", + "auth", + "authentication", + "tymon", + "laravel", + "json web token" + ], + "homepage": "https://github.com/tymondesigns/jwt-auth", + "license": "MIT", + "authors": [ + { + "name": "Sean Tymon", + "email": "tymon148@gmail.com", + "homepage": "http://tymondesigns.com", + "role": "Developer" + } + ], + "require": { + "php": ">=5.4.0", + "illuminate/support": "~5.0", + "illuminate/http": "~5.0", + "namshi/jose": "^5.0 || ^7.0", + "nesbot/carbon": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*", + "mockery/mockery": "0.9.*", + "illuminate/auth": "~5.0", + "illuminate/database": "~5.0", + "illuminate/console" : "~5.0" + }, + "autoload": { + "psr-4": { + "Tymon\\JWTAuth\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Tymon\\JWTAuth\\Test\\": "tests" + } + }, + "extra": { + "branch-alias": { + "dev-develop": "0.5-dev" + } + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/phpunit.xml.dist b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/phpunit.xml.dist new file mode 100644 index 0000000..7836abe --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/phpunit.xml.dist @@ -0,0 +1,34 @@ + + + + + tests + + + + + src/ + + src/Providers/JWTAuthServiceProvider.php + src/config/ + src/Facades/ + + + + + + + + + + + diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Blacklist.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Blacklist.php new file mode 100644 index 0000000..f562b2a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Blacklist.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth; + +use Tymon\JWTAuth\Providers\Storage\StorageInterface; + +class Blacklist +{ + /** + * @var \Tymon\JWTAuth\Providers\Storage\StorageInterface + */ + protected $storage; + + /** + * Number of minutes from issue date in which a JWT can be refreshed. + * + * @var int + */ + protected $refreshTTL = 20160; + + /** + * @param \Tymon\JWTAuth\Providers\Storage\StorageInterface $storage + */ + public function __construct(StorageInterface $storage) + { + $this->storage = $storage; + } + + /** + * Add the token (jti claim) to the blacklist. + * + * @param \Tymon\JWTAuth\Payload $payload + * @return bool + */ + public function add(Payload $payload) + { + $exp = Utils::timestamp($payload['exp']); + $refreshExp = Utils::timestamp($payload['iat'])->addMinutes($this->refreshTTL); + + // there is no need to add the token to the blacklist + // if the token has already expired AND the refresh_ttl + // has gone by + if ($exp->isPast() && $refreshExp->isPast()) { + return false; + } + + // Set the cache entry's lifetime to be equal to the amount + // of refreshable time it has remaining (which is the larger + // of `exp` and `iat+refresh_ttl`), rounded up a minute + $cacheLifetime = $exp->max($refreshExp)->addMinute()->diffInMinutes(); + + $this->storage->add($payload['jti'], [], $cacheLifetime); + + return true; + } + + /** + * Determine whether the token has been blacklisted. + * + * @param \Tymon\JWTAuth\Payload $payload + * @return bool + */ + public function has(Payload $payload) + { + return $this->storage->has($payload['jti']); + } + + /** + * Remove the token (jti claim) from the blacklist. + * + * @param \Tymon\JWTAuth\Payload $payload + * @return bool + */ + public function remove(Payload $payload) + { + return $this->storage->destroy($payload['jti']); + } + + /** + * Remove all tokens from the blacklist. + * + * @return bool + */ + public function clear() + { + $this->storage->flush(); + + return true; + } + + /** + * Set the refresh time limit. + * + * @param int + * + * @return $this + */ + public function setRefreshTTL($ttl) + { + $this->refreshTTL = (int) $ttl; + + return $this; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Audience.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Audience.php new file mode 100644 index 0000000..5a1854a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Audience.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Claims; + +class Audience extends Claim +{ + /** + * The claim name. + * + * @var string + */ + protected $name = 'aud'; +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Claim.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Claim.php new file mode 100644 index 0000000..1067d2a --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Claim.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Claims; + +use Tymon\JWTAuth\Exceptions\InvalidClaimException; + +abstract class Claim implements ClaimInterface +{ + /** + * The claim name. + * + * @var string + */ + protected $name; + + /** + * The claim value. + * + * @var mixed + */ + private $value; + + /** + * @param mixed $value + */ + public function __construct($value) + { + $this->setValue($value); + } + + /** + * Set the claim value, and call a validate method if available. + * + * @param $value + * @throws \Tymon\JWTAuth\Exceptions\InvalidClaimException + * @return $this + */ + public function setValue($value) + { + if (! $this->validate($value)) { + throw new InvalidClaimException('Invalid value provided for claim "'.$this->getName().'": '.$value); + } + + $this->value = $value; + + return $this; + } + + /** + * Get the claim value. + * + * @return mixed + */ + public function getValue() + { + return $this->value; + } + + /** + * Set the claim name. + * + * @param string $name + * @return $this + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } + + /** + * Get the claim name. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Validate the Claim value. + * + * @param $value + * @return bool + */ + protected function validate($value) + { + return true; + } + + /** + * Build a key value array comprising of the claim name and value. + * + * @return array + */ + public function toArray() + { + return [$this->getName() => $this->getValue()]; + } + + /** + * Get the claim as a string. + * + * @return string + */ + public function __toString() + { + return json_encode($this->toArray(), JSON_UNESCAPED_SLASHES); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/ClaimInterface.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/ClaimInterface.php new file mode 100644 index 0000000..8768c71 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/ClaimInterface.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Claims; + +interface ClaimInterface +{ + /** + * Set the claim value, and call a validate method if available. + * + * @param mixed + * @return Claim + */ + public function setValue($value); + + /** + * Get the claim value. + * + * @return mixed + */ + public function getValue(); + + /** + * Set the claim name. + * + * @param string $name + * @return Claim + */ + public function setName($name); + + /** + * Get the claim name. + * + * @return string + */ + public function getName(); +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Custom.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Custom.php new file mode 100644 index 0000000..b9a8f23 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Custom.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Claims; + +class Custom extends Claim +{ + /** + * @param string $name + * @param mixed $value + */ + public function __construct($name, $value) + { + parent::__construct($value); + $this->setName($name); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Expiration.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Expiration.php new file mode 100644 index 0000000..48f5171 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Expiration.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Claims; + +class Expiration extends Claim +{ + /** + * The claim name. + * + * @var string + */ + protected $name = 'exp'; + + /** + * Validate the expiry claim. + * + * @param mixed $value + * @return bool + */ + protected function validate($value) + { + return is_numeric($value); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Factory.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Factory.php new file mode 100644 index 0000000..696e30b --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Factory.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Claims; + +class Factory +{ + /** + * @var array + */ + private static $classMap = [ + 'aud' => 'Tymon\JWTAuth\Claims\Audience', + 'exp' => 'Tymon\JWTAuth\Claims\Expiration', + 'iat' => 'Tymon\JWTAuth\Claims\IssuedAt', + 'iss' => 'Tymon\JWTAuth\Claims\Issuer', + 'jti' => 'Tymon\JWTAuth\Claims\JwtId', + 'nbf' => 'Tymon\JWTAuth\Claims\NotBefore', + 'sub' => 'Tymon\JWTAuth\Claims\Subject', + ]; + + /** + * Get the instance of the claim when passing the name and value. + * + * @param string $name + * @param mixed $value + * @return \Tymon\JWTAuth\Claims\Claim + */ + public function get($name, $value) + { + if ($this->has($name)) { + return new self::$classMap[$name]($value); + } + + return new Custom($name, $value); + } + + /** + * Check whether the claim exists. + * + * @param string $name + * @return bool + */ + public function has($name) + { + return array_key_exists($name, self::$classMap); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/IssuedAt.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/IssuedAt.php new file mode 100644 index 0000000..89bea75 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/IssuedAt.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Claims; + +class IssuedAt extends Claim +{ + /** + * The claim name. + * + * @var string + */ + protected $name = 'iat'; + + /** + * Validate the issued at claim. + * + * @param mixed $value + * @return bool + */ + protected function validate($value) + { + return is_numeric($value); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Issuer.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Issuer.php new file mode 100644 index 0000000..c20ba82 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Issuer.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Claims; + +class Issuer extends Claim +{ + /** + * The claim name. + * + * @var string + */ + protected $name = 'iss'; +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/JwtId.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/JwtId.php new file mode 100644 index 0000000..15a3287 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/JwtId.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Claims; + +class JwtId extends Claim +{ + /** + * The claim name. + * + * @var string + */ + protected $name = 'jti'; +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/NotBefore.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/NotBefore.php new file mode 100644 index 0000000..ee15a53 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/NotBefore.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Claims; + +class NotBefore extends Claim +{ + /** + * The claim name. + * + * @var string + */ + protected $name = 'nbf'; + + /** + * Validate the not before claim. + * + * @param mixed $value + * @return bool + */ + protected function validate($value) + { + return is_numeric($value); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Subject.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Subject.php new file mode 100644 index 0000000..71b0514 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Claims/Subject.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Claims; + +class Subject extends Claim +{ + /** + * The claim name. + * + * @var string + */ + protected $name = 'sub'; +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Commands/JWTGenerateCommand.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Commands/JWTGenerateCommand.php new file mode 100644 index 0000000..da20e54 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Commands/JWTGenerateCommand.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Commands; + +use Illuminate\Support\Str; +use Illuminate\Console\Command; +use Symfony\Component\Console\Input\InputOption; + +class JWTGenerateCommand extends Command +{ + /** + * The console command name. + * + * @var string + */ + protected $name = 'jwt:generate'; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Set the JWTAuth secret key used to sign the tokens'; + + /** + * Execute the console command. + * + * @return void + */ + public function handle() + { + $key = $this->getRandomKey(); + + if ($this->option('show')) { + return $this->line(''.$key.''); + } + + $path = config_path('jwt.php'); + + if (file_exists($path)) { + file_put_contents($path, str_replace( + $this->laravel['config']['jwt.secret'], $key, file_get_contents($path) + )); + } + + $this->laravel['config']['jwt.secret'] = $key; + + $this->info("jwt-auth secret [$key] set successfully."); + } + + /** + * Generate a random key for the JWT Auth secret. + * + * @return string + */ + protected function getRandomKey() + { + return Str::random(32); + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions() + { + return [ + ['show', null, InputOption::VALUE_NONE, 'Simply display the key instead of modifying files.'], + ]; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/InvalidClaimException.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/InvalidClaimException.php new file mode 100644 index 0000000..b164672 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/InvalidClaimException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Exceptions; + +class InvalidClaimException extends JWTException +{ + /** + * @var int + */ + protected $statusCode = 400; +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/JWTException.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/JWTException.php new file mode 100644 index 0000000..5473f04 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/JWTException.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Exceptions; + +class JWTException extends \Exception +{ + /** + * @var int + */ + protected $statusCode = 500; + + /** + * @param string $message + * @param int $statusCode + */ + public function __construct($message = 'An error occurred', $statusCode = null) + { + parent::__construct($message); + + if (! is_null($statusCode)) { + $this->setStatusCode($statusCode); + } + } + + /** + * @param int $statusCode + */ + public function setStatusCode($statusCode) + { + $this->statusCode = $statusCode; + } + + /** + * @return int the status code + */ + public function getStatusCode() + { + return $this->statusCode; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/PayloadException.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/PayloadException.php new file mode 100644 index 0000000..4767abd --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/PayloadException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Exceptions; + +class PayloadException extends JWTException +{ + /** + * @var int + */ + protected $statusCode = 500; +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/TokenBlacklistedException.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/TokenBlacklistedException.php new file mode 100644 index 0000000..58bd582 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/TokenBlacklistedException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Exceptions; + +class TokenBlacklistedException extends TokenInvalidException +{ + /** + * @var int + */ + protected $statusCode = 401; +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/TokenExpiredException.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/TokenExpiredException.php new file mode 100644 index 0000000..d613577 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/TokenExpiredException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Exceptions; + +class TokenExpiredException extends JWTException +{ + /** + * @var int + */ + protected $statusCode = 401; +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/TokenInvalidException.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/TokenInvalidException.php new file mode 100644 index 0000000..6740d59 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Exceptions/TokenInvalidException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Exceptions; + +class TokenInvalidException extends JWTException +{ + /** + * @var int + */ + protected $statusCode = 400; +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Facades/JWTAuth.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Facades/JWTAuth.php new file mode 100644 index 0000000..419b590 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Facades/JWTAuth.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Facades; + +use Illuminate\Support\Facades\Facade; + +class JWTAuth extends Facade +{ + /** + * Get the registered name of the component. + * + * @return string + */ + protected static function getFacadeAccessor() + { + return 'tymon.jwt.auth'; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Facades/JWTFactory.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Facades/JWTFactory.php new file mode 100644 index 0000000..f43ff46 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Facades/JWTFactory.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Facades; + +use Illuminate\Support\Facades\Facade; + +class JWTFactory extends Facade +{ + /** + * Get the registered name of the component. + * + * @return string + */ + protected static function getFacadeAccessor() + { + return 'tymon.jwt.payload.factory'; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/JWTAuth.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/JWTAuth.php new file mode 100644 index 0000000..9e8b627 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/JWTAuth.php @@ -0,0 +1,343 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth; + +use Illuminate\Http\Request; +use Tymon\JWTAuth\Exceptions\JWTException; +use Tymon\JWTAuth\Providers\Auth\AuthInterface; +use Tymon\JWTAuth\Providers\User\UserInterface; + +class JWTAuth +{ + /** + * @var \Tymon\JWTAuth\JWTManager + */ + protected $manager; + + /** + * @var \Tymon\JWTAuth\Providers\User\UserInterface + */ + protected $user; + + /** + * @var \Tymon\JWTAuth\Providers\Auth\AuthInterface + */ + protected $auth; + + /** + * @var \Illuminate\Http\Request + */ + protected $request; + + /** + * @var string + */ + protected $identifier = 'id'; + + /** + * @var \Tymon\JWTAuth\Token + */ + protected $token; + + /** + * @param \Tymon\JWTAuth\JWTManager $manager + * @param \Tymon\JWTAuth\Providers\User\UserInterface $user + * @param \Tymon\JWTAuth\Providers\Auth\AuthInterface $auth + * @param \Illuminate\Http\Request $request + */ + public function __construct(JWTManager $manager, UserInterface $user, AuthInterface $auth, Request $request) + { + $this->manager = $manager; + $this->user = $user; + $this->auth = $auth; + $this->request = $request; + } + + /** + * Find a user using the user identifier in the subject claim. + * + * @param bool|string $token + * + * @return mixed + */ + public function toUser($token = false) + { + $payload = $this->getPayload($token); + + if (! $user = $this->user->getBy($this->identifier, $payload['sub'])) { + return false; + } + + return $user; + } + + /** + * Generate a token using the user identifier as the subject claim. + * + * @param mixed $user + * @param array $customClaims + * + * @return string + */ + public function fromUser($user, array $customClaims = []) + { + $payload = $this->makePayload($user->{$this->identifier}, $customClaims); + + return $this->manager->encode($payload)->get(); + } + + /** + * Attempt to authenticate the user and return the token. + * + * @param array $credentials + * @param array $customClaims + * + * @return false|string + */ + public function attempt(array $credentials = [], array $customClaims = []) + { + if (! $this->auth->byCredentials($credentials)) { + return false; + } + + return $this->fromUser($this->auth->user(), $customClaims); + } + + /** + * Authenticate a user via a token. + * + * @param mixed $token + * + * @return mixed + */ + public function authenticate($token = false) + { + $id = $this->getPayload($token)->get('sub'); + + if (! $this->auth->byId($id)) { + return false; + } + + return $this->auth->user(); + } + + /** + * Refresh an expired token. + * + * @param mixed $token + * + * @return string + */ + public function refresh($token = false) + { + $this->requireToken($token); + + return $this->manager->refresh($this->token)->get(); + } + + /** + * Invalidate a token (add it to the blacklist). + * + * @param mixed $token + * + * @return bool + */ + public function invalidate($token = false) + { + $this->requireToken($token); + + return $this->manager->invalidate($this->token); + } + + /** + * Get the token. + * + * @return bool|string + */ + public function getToken() + { + if (! $this->token) { + try { + $this->parseToken(); + } catch (JWTException $e) { + return false; + } + } + + return $this->token; + } + + /** + * Get the raw Payload instance. + * + * @param mixed $token + * + * @return \Tymon\JWTAuth\Payload + */ + public function getPayload($token = false) + { + $this->requireToken($token); + + return $this->manager->decode($this->token); + } + + /** + * Parse the token from the request. + * + * @param string $query + * + * @return JWTAuth + */ + public function parseToken($method = 'bearer', $header = 'authorization', $query = 'token') + { + if (! $token = $this->parseAuthHeader($header, $method)) { + if (! $token = $this->request->query($query, false)) { + throw new JWTException('The token could not be parsed from the request', 400); + } + } + + return $this->setToken($token); + } + + /** + * Parse token from the authorization header. + * + * @param string $header + * @param string $method + * + * @return false|string + */ + protected function parseAuthHeader($header = 'authorization', $method = 'bearer') + { + $header = $this->request->headers->get($header); + + if (! starts_with(strtolower($header), $method)) { + return false; + } + + return trim(str_ireplace($method, '', $header)); + } + + /** + * Create a Payload instance. + * + * @param mixed $subject + * @param array $customClaims + * + * @return \Tymon\JWTAuth\Payload + */ + protected function makePayload($subject, array $customClaims = []) + { + return $this->manager->getPayloadFactory()->make( + array_merge($customClaims, ['sub' => $subject]) + ); + } + + /** + * Set the identifier. + * + * @param string $identifier + * + * @return $this + */ + public function setIdentifier($identifier) + { + $this->identifier = $identifier; + + return $this; + } + + /** + * Get the identifier. + * + * @return string + */ + public function getIdentifier() + { + return $this->identifier; + } + + /** + * Set the token. + * + * @param string $token + * + * @return $this + */ + public function setToken($token) + { + $this->token = new Token($token); + + return $this; + } + + /** + * Ensure that a token is available. + * + * @param mixed $token + * + * @return JWTAuth + * + * @throws \Tymon\JWTAuth\Exceptions\JWTException + */ + protected function requireToken($token) + { + if ($token) { + return $this->setToken($token); + } elseif ($this->token) { + return $this; + } else { + throw new JWTException('A token is required', 400); + } + } + + /** + * Set the request instance. + * + * @param Request $request + */ + public function setRequest(Request $request) + { + $this->request = $request; + + return $this; + } + + /** + * Get the JWTManager instance. + * + * @return \Tymon\JWTAuth\JWTManager + */ + public function manager() + { + return $this->manager; + } + + /** + * Magically call the JWT Manager. + * + * @param string $method + * @param array $parameters + * + * @return mixed + * + * @throws \BadMethodCallException + */ + public function __call($method, $parameters) + { + if (method_exists($this->manager, $method)) { + return call_user_func_array([$this->manager, $method], $parameters); + } + + throw new \BadMethodCallException("Method [$method] does not exist."); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/JWTManager.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/JWTManager.php new file mode 100644 index 0000000..603e705 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/JWTManager.php @@ -0,0 +1,183 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth; + +use Tymon\JWTAuth\Exceptions\JWTException; +use Tymon\JWTAuth\Providers\JWT\JWTInterface; +use Tymon\JWTAuth\Exceptions\TokenBlacklistedException; + +class JWTManager +{ + /** + * @var \Tymon\JWTAuth\Providers\JWT\JWTInterface + */ + protected $jwt; + + /** + * @var \Tymon\JWTAuth\Blacklist + */ + protected $blacklist; + + /** + * @var \Tymon\JWTAuth\PayloadFactory + */ + protected $payloadFactory; + + /** + * @var bool + */ + protected $blacklistEnabled = true; + + /** + * @var bool + */ + protected $refreshFlow = false; + + /** + * @param \Tymon\JWTAuth\Providers\JWT\JWTInterface $jwt + * @param \Tymon\JWTAuth\Blacklist $blacklist + * @param \Tymon\JWTAuth\PayloadFactory $payloadFactory + */ + public function __construct(JWTInterface $jwt, Blacklist $blacklist, PayloadFactory $payloadFactory) + { + $this->jwt = $jwt; + $this->blacklist = $blacklist; + $this->payloadFactory = $payloadFactory; + } + + /** + * Encode a Payload and return the Token. + * + * @param \Tymon\JWTAuth\Payload $payload + * @return \Tymon\JWTAuth\Token + */ + public function encode(Payload $payload) + { + $token = $this->jwt->encode($payload->get()); + + return new Token($token); + } + + /** + * Decode a Token and return the Payload. + * + * @param \Tymon\JWTAuth\Token $token + * @return Payload + * @throws TokenBlacklistedException + */ + public function decode(Token $token) + { + $payloadArray = $this->jwt->decode($token->get()); + + $payload = $this->payloadFactory->setRefreshFlow($this->refreshFlow)->make($payloadArray); + + if ($this->blacklistEnabled && $this->blacklist->has($payload)) { + throw new TokenBlacklistedException('The token has been blacklisted'); + } + + return $payload; + } + + /** + * Refresh a Token and return a new Token. + * + * @param \Tymon\JWTAuth\Token $token + * @return \Tymon\JWTAuth\Token + */ + public function refresh(Token $token) + { + $payload = $this->setRefreshFlow()->decode($token); + + if ($this->blacklistEnabled) { + // invalidate old token + $this->blacklist->add($payload); + } + + // return the new token + return $this->encode( + $this->payloadFactory->make([ + 'sub' => $payload['sub'], + 'iat' => $payload['iat'], + ]) + ); + } + + /** + * Invalidate a Token by adding it to the blacklist. + * + * @param Token $token + * @return bool + */ + public function invalidate(Token $token) + { + if (! $this->blacklistEnabled) { + throw new JWTException('You must have the blacklist enabled to invalidate a token.'); + } + + return $this->blacklist->add($this->decode($token)); + } + + /** + * Get the PayloadFactory instance. + * + * @return \Tymon\JWTAuth\PayloadFactory + */ + public function getPayloadFactory() + { + return $this->payloadFactory; + } + + /** + * Get the JWTProvider instance. + * + * @return \Tymon\JWTAuth\Providers\JWT\JWTInterface + */ + public function getJWTProvider() + { + return $this->jwt; + } + + /** + * Get the Blacklist instance. + * + * @return \Tymon\JWTAuth\Blacklist + */ + public function getBlacklist() + { + return $this->blacklist; + } + + /** + * Set whether the blacklist is enabled. + * + * @param bool $enabled + */ + public function setBlacklistEnabled($enabled) + { + $this->blacklistEnabled = $enabled; + + return $this; + } + + /** + * Set the refresh flow. + * + * @param bool $refreshFlow + * @return $this + */ + public function setRefreshFlow($refreshFlow = true) + { + $this->refreshFlow = $refreshFlow; + + return $this; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Middleware/BaseMiddleware.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Middleware/BaseMiddleware.php new file mode 100644 index 0000000..9715f0c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Middleware/BaseMiddleware.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Middleware; + +use Tymon\JWTAuth\JWTAuth; +use Illuminate\Contracts\Events\Dispatcher; +use Illuminate\Contracts\Routing\ResponseFactory; + +abstract class BaseMiddleware +{ + /** + * @var \Illuminate\Contracts\Routing\ResponseFactory + */ + protected $response; + + /** + * @var \Illuminate\Contracts\Events\Dispatcher + */ + protected $events; + + /** + * @var \Tymon\JWTAuth\JWTAuth + */ + protected $auth; + + /** + * Create a new BaseMiddleware instance. + * + * @param \Illuminate\Contracts\Routing\ResponseFactory $response + * @param \Illuminate\Contracts\Events\Dispatcher $events + * @param \Tymon\JWTAuth\JWTAuth $auth + */ + public function __construct(ResponseFactory $response, Dispatcher $events, JWTAuth $auth) + { + $this->response = $response; + $this->events = $events; + $this->auth = $auth; + } + + /** + * Fire event and return the response. + * + * @param string $event + * @param string $error + * @param int $status + * @param array $payload + * @return mixed + */ + protected function respond($event, $error, $status, $payload = []) + { + $response = $this->events->fire($event, $payload, true); + + return $response ?: $this->response->json(['error' => $error], $status); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Middleware/GetUserFromToken.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Middleware/GetUserFromToken.php new file mode 100644 index 0000000..af3b21c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Middleware/GetUserFromToken.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Middleware; + +use Tymon\JWTAuth\Exceptions\JWTException; +use Tymon\JWTAuth\Exceptions\TokenExpiredException; + +class GetUserFromToken extends BaseMiddleware +{ + /** + * Handle an incoming request. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @return mixed + */ + public function handle($request, \Closure $next) + { + if (! $token = $this->auth->setRequest($request)->getToken()) { + return $this->respond('tymon.jwt.absent', 'token_not_provided', 400); + } + + try { + $user = $this->auth->authenticate($token); + } catch (TokenExpiredException $e) { + return $this->respond('tymon.jwt.expired', 'token_expired', $e->getStatusCode(), [$e]); + } catch (JWTException $e) { + return $this->respond('tymon.jwt.invalid', 'token_invalid', $e->getStatusCode(), [$e]); + } + + if (! $user) { + return $this->respond('tymon.jwt.user_not_found', 'user_not_found', 404); + } + + $this->events->fire('tymon.jwt.valid', $user); + + return $next($request); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Middleware/RefreshToken.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Middleware/RefreshToken.php new file mode 100644 index 0000000..a54774c --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Middleware/RefreshToken.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Middleware; + +use Tymon\JWTAuth\Exceptions\JWTException; +use Tymon\JWTAuth\Exceptions\TokenExpiredException; + +class RefreshToken extends BaseMiddleware +{ + /** + * Handle an incoming request. + * + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @return mixed + */ + public function handle($request, \Closure $next) + { + $response = $next($request); + + try { + $newToken = $this->auth->setRequest($request)->parseToken()->refresh(); + } catch (TokenExpiredException $e) { + return $this->respond('tymon.jwt.expired', 'token_expired', $e->getStatusCode(), [$e]); + } catch (JWTException $e) { + return $this->respond('tymon.jwt.invalid', 'token_invalid', $e->getStatusCode(), [$e]); + } + + // send the refreshed token back to the client + $response->headers->set('Authorization', 'Bearer '.$newToken); + + return $response; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Payload.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Payload.php new file mode 100644 index 0000000..79cdb8d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Payload.php @@ -0,0 +1,175 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth; + +use Tymon\JWTAuth\Claims\Claim; +use Tymon\JWTAuth\Exceptions\PayloadException; +use Tymon\JWTAuth\Validators\PayloadValidator; + +class Payload implements \ArrayAccess +{ + /** + * The array of claims. + * + * @var \Tymon\JWTAuth\Claims\Claim[] + */ + private $claims = []; + + /** + * Build the Payload. + * + * @param array $claims + * @param \Tymon\JWTAuth\Validators\PayloadValidator $validator + * @param bool $refreshFlow + */ + public function __construct(array $claims, PayloadValidator $validator, $refreshFlow = false) + { + $this->claims = $claims; + + $validator->setRefreshFlow($refreshFlow)->check($this->toArray()); + } + + /** + * Get the array of claim instances. + * + * @return \Tymon\JWTAuth\Claims\Claim[] + */ + public function getClaims() + { + return $this->claims; + } + + /** + * Get the array of claims. + * + * @return array + */ + public function toArray() + { + $results = []; + foreach ($this->claims as $claim) { + $results[$claim->getName()] = $claim->getValue(); + } + + return $results; + } + + /** + * Get the payload. + * + * @param string $claim + * @return mixed + */ + public function get($claim = null) + { + if (! is_null($claim)) { + if (is_array($claim)) { + return array_map([$this, 'get'], $claim); + } + + return array_get($this->toArray(), $claim, false); + } + + return $this->toArray(); + } + + /** + * Determine whether the payload has the claim. + * + * @param \Tymon\JWTAuth\Claims\Claim $claim + * @return bool + */ + public function has(Claim $claim) + { + return in_array($claim, $this->claims); + } + + /** + * Get the payload as a string. + * + * @return string + */ + public function __toString() + { + return json_encode($this->toArray()); + } + + /** + * Determine if an item exists at an offset. + * + * @param mixed $key + * @return bool + */ + public function offsetExists($key) + { + return array_key_exists($key, $this->toArray()); + } + + /** + * Get an item at a given offset. + * + * @param mixed $key + * @return mixed + */ + public function offsetGet($key) + { + return array_get($this->toArray(), $key, []); + } + + /** + * Don't allow changing the payload as it should be immutable. + * + * @param mixed $key + * @param mixed $value + * @throws Exceptions\PayloadException + * @return void + */ + public function offsetSet($key, $value) + { + throw new PayloadException('The payload is immutable'); + } + + /** + * Don't allow changing the payload as it should be immutable. + * + * @param string $key + * @throws Exceptions\PayloadException + * @return void + */ + public function offsetUnset($key) + { + throw new PayloadException('The payload is immutable'); + } + + /** + * Magically get a claim value. + * + * @param string $method + * @param array $parameters + * @return mixed + * @throws \BadMethodCallException + */ + public function __call($method, $parameters) + { + if (! method_exists($this, $method) && starts_with($method, 'get')) { + $class = sprintf('Tymon\\JWTAuth\\Claims\\%s', substr($method, 3)); + + foreach ($this->claims as $claim) { + if (get_class($claim) === $class) { + return $claim->getValue(); + } + } + } + + throw new \BadMethodCallException(sprintf('The claim [%s] does not exist on the payload.', $method)); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/PayloadFactory.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/PayloadFactory.php new file mode 100644 index 0000000..352e413 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/PayloadFactory.php @@ -0,0 +1,245 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth; + +use Illuminate\Support\Str; +use Illuminate\Http\Request; +use Tymon\JWTAuth\Claims\Factory; +use Tymon\JWTAuth\Validators\PayloadValidator; + +class PayloadFactory +{ + /** + * @var \Tymon\JWTAuth\Claims\Factory + */ + protected $claimFactory; + + /** + * @var \Illuminate\Http\Request + */ + protected $request; + + /** + * @var \Tymon\JWTAuth\Validators\PayloadValidator + */ + protected $validator; + + /** + * @var int + */ + protected $ttl = 60; + + /** + * @var bool + */ + protected $refreshFlow = false; + + /** + * @var array + */ + protected $defaultClaims = ['iss', 'iat', 'exp', 'nbf', 'jti']; + + /** + * @var array + */ + protected $claims = []; + + /** + * @param \Tymon\JWTAuth\Claims\Factory $claimFactory + * @param \Illuminate\Http\Request $request + * @param \Tymon\JWTAuth\Validators\PayloadValidator $validator + */ + public function __construct(Factory $claimFactory, Request $request, PayloadValidator $validator) + { + $this->claimFactory = $claimFactory; + $this->request = $request; + $this->validator = $validator; + } + + /** + * Create the Payload instance. + * + * @param array $customClaims + * @return \Tymon\JWTAuth\Payload + */ + public function make(array $customClaims = []) + { + $claims = $this->buildClaims($customClaims)->resolveClaims(); + + return new Payload($claims, $this->validator, $this->refreshFlow); + } + + /** + * Add an array of claims to the Payload. + * + * @param array $claims + * @return $this + */ + public function addClaims(array $claims) + { + foreach ($claims as $name => $value) { + $this->addClaim($name, $value); + } + + return $this; + } + + /** + * Add a claim to the Payload. + * + * @param string $name + * @param mixed $value + * @return $this + */ + public function addClaim($name, $value) + { + $this->claims[$name] = $value; + + return $this; + } + + /** + * Build the default claims. + * + * @param array $customClaims + * @return $this + */ + protected function buildClaims(array $customClaims) + { + // add any custom claims first + $this->addClaims($customClaims); + + foreach ($this->defaultClaims as $claim) { + if (! array_key_exists($claim, $customClaims)) { + $this->addClaim($claim, $this->$claim()); + } + } + + return $this; + } + + /** + * Build out the Claim DTO's. + * + * @return array + */ + public function resolveClaims() + { + $resolved = []; + foreach ($this->claims as $name => $value) { + $resolved[] = $this->claimFactory->get($name, $value); + } + + return $resolved; + } + + /** + * Set the Issuer (iss) claim. + * + * @return string + */ + public function iss() + { + return $this->request->url(); + } + + /** + * Set the Issued At (iat) claim. + * + * @return int + */ + public function iat() + { + return Utils::now()->timestamp; + } + + /** + * Set the Expiration (exp) claim. + * + * @return int + */ + public function exp() + { + return Utils::now()->addMinutes($this->ttl)->timestamp; + } + + /** + * Set the Not Before (nbf) claim. + * + * @return int + */ + public function nbf() + { + return Utils::now()->timestamp; + } + + /** + * Set a unique id (jti) for the token. + * + * @return string + */ + protected function jti() + { + return Str::random(); + } + + /** + * Set the token ttl (in minutes). + * + * @param int $ttl + * @return $this + */ + public function setTTL($ttl) + { + $this->ttl = $ttl; + + return $this; + } + + /** + * Get the token ttl. + * + * @return int + */ + public function getTTL() + { + return $this->ttl; + } + + /** + * Set the refresh flow. + * + * @param bool $refreshFlow + * @return $this + */ + public function setRefreshFlow($refreshFlow = true) + { + $this->refreshFlow = $refreshFlow; + + return $this; + } + + /** + * Magically add a claim. + * + * @param string $method + * @param array $parameters + * @return PayloadFactory + * @throws \BadMethodCallException + */ + public function __call($method, $parameters) + { + $this->addClaim($method, $parameters[0]); + + return $this; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Auth/AuthInterface.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Auth/AuthInterface.php new file mode 100644 index 0000000..f6f1dd7 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Auth/AuthInterface.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Providers\Auth; + +interface AuthInterface +{ + /** + * Check a user's credentials. + * + * @param array $credentials + * @return bool + */ + public function byCredentials(array $credentials = []); + + /** + * Authenticate a user via the id. + * + * @param mixed $id + * @return bool + */ + public function byId($id); + + /** + * Get the currently authenticated user. + * + * @return mixed + */ + public function user(); +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Auth/IlluminateAuthAdapter.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Auth/IlluminateAuthAdapter.php new file mode 100644 index 0000000..4eaccbd --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Auth/IlluminateAuthAdapter.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Providers\Auth; + +use Illuminate\Auth\AuthManager; + +class IlluminateAuthAdapter implements AuthInterface +{ + /** + * @var \Illuminate\Auth\AuthManager + */ + protected $auth; + + /** + * @param \Illuminate\Auth\AuthManager $auth + */ + public function __construct(AuthManager $auth) + { + $this->auth = $auth; + } + + /** + * Check a user's credentials. + * + * @param array $credentials + * @return bool + */ + public function byCredentials(array $credentials = []) + { + return $this->auth->once($credentials); + } + + /** + * Authenticate a user via the id. + * + * @param mixed $id + * @return bool + */ + public function byId($id) + { + return $this->auth->onceUsingId($id); + } + + /** + * Get the currently authenticated user. + * + * @return mixed + */ + public function user() + { + return $this->auth->user(); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWT/JWTInterface.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWT/JWTInterface.php new file mode 100644 index 0000000..0852923 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWT/JWTInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Providers\JWT; + +interface JWTInterface +{ + /** + * @param array $payload + * @return string + */ + public function encode(array $payload); + + /** + * @param string $token + * @return array + */ + public function decode($token); +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWT/JWTProvider.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWT/JWTProvider.php new file mode 100644 index 0000000..e15e848 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWT/JWTProvider.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Providers\JWT; + +abstract class JWTProvider +{ + /** + * @var string + */ + protected $secret; + + /** + * @var string + */ + protected $algo; + + /** + * @param string $secret + * @param string $algo + */ + public function __construct($secret, $algo = 'HS256') + { + $this->secret = $secret; + $this->algo = $algo; + } + + /** + * Set the algorithm used to sign the token. + * + * @param string $algo + * @return self + */ + public function setAlgo($algo) + { + $this->algo = $algo; + + return $this; + } + + /** + * Get the algorithm used to sign the token. + * + * @return string + */ + public function getAlgo() + { + return $this->algo; + } + + /** + * Set the secret used to sign the token. + * + * @param string $secret + * + * @return $this + */ + public function setSecret($secret) + { + $this->secret = $secret; + + return $this; + } + + /** + * Get the secret used to sign the token. + * + * @return string + */ + public function getSecret() + { + return $this->secret; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWT/NamshiAdapter.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWT/NamshiAdapter.php new file mode 100644 index 0000000..e291474 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWT/NamshiAdapter.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Providers\JWT; + +use Exception; +use Namshi\JOSE\JWS; +use Tymon\JWTAuth\Exceptions\JWTException; +use Tymon\JWTAuth\Exceptions\TokenInvalidException; + +class NamshiAdapter extends JWTProvider implements JWTInterface +{ + /** + * @var \Namshi\JOSE\JWS + */ + protected $jws; + + /** + * @param string $secret + * @param string $algo + * @param null $driver + */ + public function __construct($secret, $algo, $driver = null) + { + parent::__construct($secret, $algo); + + $this->jws = $driver ?: new JWS(['typ' => 'JWT', 'alg' => $algo]); + } + + /** + * Create a JSON Web Token. + * + * @return string + * @throws \Tymon\JWTAuth\Exceptions\JWTException + */ + public function encode(array $payload) + { + try { + $this->jws->setPayload($payload)->sign($this->secret); + + return $this->jws->getTokenString(); + } catch (Exception $e) { + throw new JWTException('Could not create token: '.$e->getMessage()); + } + } + + /** + * Decode a JSON Web Token. + * + * @param string $token + * @return array + * @throws \Tymon\JWTAuth\Exceptions\JWTException + */ + public function decode($token) + { + try { + $jws = JWS::load($token); + } catch (Exception $e) { + throw new TokenInvalidException('Could not decode token: '.$e->getMessage()); + } + + if (! $jws->verify($this->secret, $this->algo)) { + throw new TokenInvalidException('Token Signature could not be verified.'); + } + + return $jws->getPayload(); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWTAuthServiceProvider.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWTAuthServiceProvider.php new file mode 100644 index 0000000..6bb4365 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/JWTAuthServiceProvider.php @@ -0,0 +1,278 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Providers; + +use Tymon\JWTAuth\JWTAuth; +use Tymon\JWTAuth\Blacklist; +use Tymon\JWTAuth\JWTManager; +use Tymon\JWTAuth\Claims\Factory; +use Tymon\JWTAuth\PayloadFactory; +use Illuminate\Support\ServiceProvider; +use Tymon\JWTAuth\Commands\JWTGenerateCommand; +use Tymon\JWTAuth\Validators\PayloadValidator; + +class JWTAuthServiceProvider extends ServiceProvider +{ + /** + * Indicates if loading of the provider is deferred. + * + * @var bool + */ + protected $defer = false; + + /** + * Boot the service provider. + */ + public function boot() + { + $this->publishes([ + __DIR__.'/../config/config.php' => config_path('jwt.php'), + ], 'config'); + + $this->bootBindings(); + + $this->commands('tymon.jwt.generate'); + } + + /** + * Bind some Interfaces and implementations. + */ + protected function bootBindings() + { + $this->app->singleton('Tymon\JWTAuth\JWTAuth', function ($app) { + return $app['tymon.jwt.auth']; + }); + + $this->app->singleton('Tymon\JWTAuth\Providers\User\UserInterface', function ($app) { + return $app['tymon.jwt.provider.user']; + }); + + $this->app->singleton('Tymon\JWTAuth\Providers\JWT\JWTInterface', function ($app) { + return $app['tymon.jwt.provider.jwt']; + }); + + $this->app->singleton('Tymon\JWTAuth\Providers\Auth\AuthInterface', function ($app) { + return $app['tymon.jwt.provider.auth']; + }); + + $this->app->singleton('Tymon\JWTAuth\Providers\Storage\StorageInterface', function ($app) { + return $app['tymon.jwt.provider.storage']; + }); + + $this->app->singleton('Tymon\JWTAuth\JWTManager', function ($app) { + return $app['tymon.jwt.manager']; + }); + + $this->app->singleton('Tymon\JWTAuth\Blacklist', function ($app) { + return $app['tymon.jwt.blacklist']; + }); + + $this->app->singleton('Tymon\JWTAuth\PayloadFactory', function ($app) { + return $app['tymon.jwt.payload.factory']; + }); + + $this->app->singleton('Tymon\JWTAuth\Claims\Factory', function ($app) { + return $app['tymon.jwt.claim.factory']; + }); + + $this->app->singleton('Tymon\JWTAuth\Validators\PayloadValidator', function ($app) { + return $app['tymon.jwt.validators.payload']; + }); + } + + /** + * Register the service provider. + * + * @return void + */ + public function register() + { + // register providers + $this->registerUserProvider(); + $this->registerJWTProvider(); + $this->registerAuthProvider(); + $this->registerStorageProvider(); + $this->registerJWTBlacklist(); + + $this->registerClaimFactory(); + $this->registerJWTManager(); + + $this->registerJWTAuth(); + $this->registerPayloadValidator(); + $this->registerPayloadFactory(); + $this->registerJWTCommand(); + + $this->mergeConfigFrom(__DIR__.'/../config/config.php', 'jwt'); + } + + /** + * Register the bindings for the User provider. + */ + protected function registerUserProvider() + { + $this->app->singleton('tymon.jwt.provider.user', function ($app) { + $provider = $this->config('providers.user'); + $model = $app->make($this->config('user')); + + return new $provider($model); + }); + } + + /** + * Register the bindings for the JSON Web Token provider. + */ + protected function registerJWTProvider() + { + $this->app->singleton('tymon.jwt.provider.jwt', function ($app) { + $secret = $this->config('secret'); + $algo = $this->config('algo'); + $provider = $this->config('providers.jwt'); + + return new $provider($secret, $algo); + }); + } + + /** + * Register the bindings for the Auth provider. + */ + protected function registerAuthProvider() + { + $this->app->singleton('tymon.jwt.provider.auth', function ($app) { + return $this->getConfigInstance($this->config('providers.auth')); + }); + } + + /** + * Register the bindings for the Storage provider. + */ + protected function registerStorageProvider() + { + $this->app->singleton('tymon.jwt.provider.storage', function ($app) { + return $this->getConfigInstance($this->config('providers.storage')); + }); + } + + /** + * Register the bindings for the Payload Factory. + */ + protected function registerClaimFactory() + { + $this->app->singleton('tymon.jwt.claim.factory', function () { + return new Factory(); + }); + } + + /** + * Register the bindings for the JWT Manager. + */ + protected function registerJWTManager() + { + $this->app->singleton('tymon.jwt.manager', function ($app) { + $instance = new JWTManager( + $app['tymon.jwt.provider.jwt'], + $app['tymon.jwt.blacklist'], + $app['tymon.jwt.payload.factory'] + ); + + return $instance->setBlacklistEnabled((bool) $this->config('blacklist_enabled')); + }); + } + + /** + * Register the bindings for the main JWTAuth class. + */ + protected function registerJWTAuth() + { + $this->app->singleton('tymon.jwt.auth', function ($app) { + $auth = new JWTAuth( + $app['tymon.jwt.manager'], + $app['tymon.jwt.provider.user'], + $app['tymon.jwt.provider.auth'], + $app['request'] + ); + + return $auth->setIdentifier($this->config('identifier')); + }); + } + + /** + * Register the bindings for the main JWTAuth class. + */ + protected function registerJWTBlacklist() + { + $this->app->singleton('tymon.jwt.blacklist', function ($app) { + $instance = new Blacklist($app['tymon.jwt.provider.storage']); + + return $instance->setRefreshTTL($this->config('refresh_ttl')); + }); + } + + /** + * Register the bindings for the payload validator. + */ + protected function registerPayloadValidator() + { + $this->app->singleton('tymon.jwt.validators.payload', function () { + return with(new PayloadValidator())->setRefreshTTL($this->config('refresh_ttl'))->setRequiredClaims($this->config('required_claims')); + }); + } + + /** + * Register the bindings for the Payload Factory. + */ + protected function registerPayloadFactory() + { + $this->app->singleton('tymon.jwt.payload.factory', function ($app) { + $factory = new PayloadFactory($app['tymon.jwt.claim.factory'], $app['request'], $app['tymon.jwt.validators.payload']); + + return $factory->setTTL($this->config('ttl')); + }); + } + + /** + * Register the Artisan command. + */ + protected function registerJWTCommand() + { + $this->app->singleton('tymon.jwt.generate', function () { + return new JWTGenerateCommand(); + }); + } + + /** + * Helper to get the config values. + * + * @param string $key + * @return string + */ + protected function config($key, $default = null) + { + return config("jwt.$key", $default); + } + + /** + * Get an instantiable configuration instance. Pinched from dingo/api :). + * + * @param mixed $instance + * @return object + */ + protected function getConfigInstance($instance) + { + if (is_callable($instance)) { + return call_user_func($instance, $this->app); + } elseif (is_string($instance)) { + return $this->app->make($instance); + } + + return $instance; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Storage/IlluminateCacheAdapter.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Storage/IlluminateCacheAdapter.php new file mode 100644 index 0000000..3abdee5 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Storage/IlluminateCacheAdapter.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Providers\Storage; + +use Illuminate\Cache\CacheManager; + +class IlluminateCacheAdapter implements StorageInterface +{ + /** + * @var \Illuminate\Cache\CacheManager + */ + protected $cache; + + /** + * @var string + */ + protected $tag = 'tymon.jwt'; + + /** + * @param \Illuminate\Cache\CacheManager $cache + */ + public function __construct(CacheManager $cache) + { + $this->cache = $cache; + } + + /** + * Add a new item into storage. + * + * @param string $key + * @param mixed $value + * @param int $minutes + * @return void + */ + public function add($key, $value, $minutes) + { + $this->cache()->put($key, $value, $minutes); + } + + /** + * Check whether a key exists in storage. + * + * @param string $key + * @return bool + */ + public function has($key) + { + return $this->cache()->has($key); + } + + /** + * Remove an item from storage. + * + * @param string $key + * @return bool + */ + public function destroy($key) + { + return $this->cache()->forget($key); + } + + /** + * Remove all items associated with the tag. + * + * @return void + */ + public function flush() + { + $this->cache()->flush(); + } + + /** + * Return the cache instance with tags attached. + * + * @return \Illuminate\Cache\CacheManager + */ + protected function cache() + { + if (! method_exists($this->cache, 'tags')) { + return $this->cache; + } + + return $this->cache->tags($this->tag); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Storage/StorageInterface.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Storage/StorageInterface.php new file mode 100644 index 0000000..7468ed7 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/Storage/StorageInterface.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Providers\Storage; + +interface StorageInterface +{ + /** + * @param string $key + * @param int $minutes + * @return void + */ + public function add($key, $value, $minutes); + + /** + * @param string $key + * @return bool + */ + public function has($key); + + /** + * @param string $key + * @return bool + */ + public function destroy($key); + + /** + * @return void + */ + public function flush(); +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/User/EloquentUserAdapter.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/User/EloquentUserAdapter.php new file mode 100644 index 0000000..63e80cc --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/User/EloquentUserAdapter.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Providers\User; + +use Illuminate\Database\Eloquent\Model; + +class EloquentUserAdapter implements UserInterface +{ + /** + * @var \Illuminate\Database\Eloquent\Model + */ + protected $user; + + /** + * Create a new User instance. + * + * @param \Illuminate\Database\Eloquent\Model $user + */ + public function __construct(Model $user) + { + $this->user = $user; + } + + /** + * Get the user by the given key, value. + * + * @param mixed $key + * @param mixed $value + * @return Illuminate\Database\Eloquent\Model + */ + public function getBy($key, $value) + { + return $this->user->where($key, $value)->first(); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/User/UserInterface.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/User/UserInterface.php new file mode 100644 index 0000000..6a73e3f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Providers/User/UserInterface.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Providers\User; + +interface UserInterface +{ + /** + * Get the user by the given key, value. + * + * @param string $key + * @param mixed $value + * @return Illuminate\Database\Eloquent\Model|null + */ + public function getBy($key, $value); +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Token.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Token.php new file mode 100644 index 0000000..e451aad --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Token.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth; + +use Tymon\JWTAuth\Validators\TokenValidator; + +class Token +{ + /** + * @var string + */ + private $value; + + /** + * Create a new JSON Web Token. + * + * @param string $value + */ + public function __construct($value) + { + with(new TokenValidator)->check($value); + + $this->value = $value; + } + + /** + * Get the token. + * + * @return string + */ + public function get() + { + return $this->value; + } + + /** + * Get the token when casting to string. + * + * @return string + */ + public function __toString() + { + return (string) $this->value; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Utils.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Utils.php new file mode 100644 index 0000000..9469781 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Utils.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth; + +use Carbon\Carbon; + +class Utils +{ + /** + * Get the Carbon instance for the current time. + * + * @return \Carbon\Carbon + */ + public static function now() + { + return Carbon::now(); + } + + /** + * Get the Carbon instance for the timestamp. + * + * @param int $timestamp + * @return \Carbon\Carbon + */ + public static function timestamp($timestamp) + { + return Carbon::createFromTimeStampUTC($timestamp); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/AbstractValidator.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/AbstractValidator.php new file mode 100644 index 0000000..5a3ad28 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/AbstractValidator.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Validators; + +use Tymon\JWTAuth\Exceptions\JWTException; + +abstract class AbstractValidator implements ValidatorInterface +{ + /** + * @var bool + */ + protected $refreshFlow = false; + + /** + * Helper function to return a boolean. + * + * @param array $value + * @return bool + */ + public function isValid($value) + { + try { + $this->check($value); + } catch (JWTException $e) { + return false; + } + + return true; + } + + /** + * Set the refresh flow flag. + * + * @param bool $refreshFlow + * @return $this + */ + public function setRefreshFlow($refreshFlow = true) + { + $this->refreshFlow = $refreshFlow; + + return $this; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/PayloadValidator.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/PayloadValidator.php new file mode 100644 index 0000000..80e1a86 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/PayloadValidator.php @@ -0,0 +1,127 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Validators; + +use Tymon\JWTAuth\Utils; +use Tymon\JWTAuth\Exceptions\TokenExpiredException; +use Tymon\JWTAuth\Exceptions\TokenInvalidException; + +class PayloadValidator extends AbstractValidator +{ + /** + * @var array + */ + protected $requiredClaims = ['iss', 'iat', 'exp', 'nbf', 'sub', 'jti']; + + /** + * @var int + */ + protected $refreshTTL = 20160; + + /** + * Run the validations on the payload array. + * + * @param array $value + * @return void + */ + public function check($value) + { + $this->validateStructure($value); + + if (! $this->refreshFlow) { + $this->validateTimestamps($value); + } else { + $this->validateRefresh($value); + } + } + + /** + * Ensure the payload contains the required claims and + * the claims have the relevant type. + * + * @param array $payload + * @throws \Tymon\JWTAuth\Exceptions\TokenInvalidException + * @return bool + */ + protected function validateStructure(array $payload) + { + if (count(array_diff($this->requiredClaims, array_keys($payload))) !== 0) { + throw new TokenInvalidException('JWT payload does not contain the required claims'); + } + + return true; + } + + /** + * Validate the payload timestamps. + * + * @param array $payload + * @throws \Tymon\JWTAuth\Exceptions\TokenExpiredException + * @throws \Tymon\JWTAuth\Exceptions\TokenInvalidException + * @return bool + */ + protected function validateTimestamps(array $payload) + { + if (isset($payload['nbf']) && Utils::timestamp($payload['nbf'])->isFuture()) { + throw new TokenInvalidException('Not Before (nbf) timestamp cannot be in the future', 400); + } + + if (isset($payload['iat']) && Utils::timestamp($payload['iat'])->isFuture()) { + throw new TokenInvalidException('Issued At (iat) timestamp cannot be in the future', 400); + } + + if (Utils::timestamp($payload['exp'])->isPast()) { + throw new TokenExpiredException('Token has expired'); + } + + return true; + } + + /** + * Check the token in the refresh flow context. + * + * @param $payload + * @return bool + */ + protected function validateRefresh(array $payload) + { + if (isset($payload['iat']) && Utils::timestamp($payload['iat'])->addMinutes($this->refreshTTL)->isPast()) { + throw new TokenExpiredException('Token has expired and can no longer be refreshed', 400); + } + + return true; + } + + /** + * Set the required claims. + * + * @param array $claims + */ + public function setRequiredClaims(array $claims) + { + $this->requiredClaims = $claims; + + return $this; + } + + /** + * Set the refresh ttl. + * + * @param int $ttl + */ + public function setRefreshTTL($ttl) + { + $this->refreshTTL = $ttl; + + return $this; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/TokenValidator.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/TokenValidator.php new file mode 100644 index 0000000..f68e195 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/TokenValidator.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Validators; + +use Tymon\JWTAuth\Exceptions\TokenInvalidException; + +class TokenValidator extends AbstractValidator +{ + /** + * Check the structure of the token. + * + * @param string $value + * @return void + */ + public function check($value) + { + $this->validateStructure($value); + } + + /** + * @param string $token + * @throws \Tymon\JWTAuth\Exceptions\TokenInvalidException + * @return bool + */ + protected function validateStructure($token) + { + if (count(explode('.', $token)) !== 3) { + throw new TokenInvalidException('Wrong number of segments'); + } + + return true; + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/ValidatorInterface.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/ValidatorInterface.php new file mode 100644 index 0000000..87d5dc0 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/Validators/ValidatorInterface.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Validators; + +interface ValidatorInterface +{ + /** + * Perform some checks on the value. + * + * @param mixed $value + * @return void + */ + public function check($value); + + /** + * Helper function to return a boolean. + * + * @param array $value + * @return bool + */ + public function isValid($value); +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/config/config.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/config/config.php new file mode 100644 index 0000000..b12ac03 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/src/config/config.php @@ -0,0 +1,173 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return [ + + /* + |-------------------------------------------------------------------------- + | JWT Authentication Secret + |-------------------------------------------------------------------------- + | + | Don't forget to set this, as it will be used to sign your tokens. + | A helper command is provided for this: `php artisan jwt:generate` + | + */ + + 'secret' => env('JWT_SECRET', 'changeme'), + + /* + |-------------------------------------------------------------------------- + | JWT time to live + |-------------------------------------------------------------------------- + | + | Specify the length of time (in minutes) that the token will be valid for. + | Defaults to 1 hour + | + */ + + 'ttl' => 60, + + /* + |-------------------------------------------------------------------------- + | Refresh time to live + |-------------------------------------------------------------------------- + | + | Specify the length of time (in minutes) that the token can be refreshed + | within. I.E. The user can refresh their token within a 2 week window of + | the original token being created until they must re-authenticate. + | Defaults to 2 weeks + | + */ + + 'refresh_ttl' => 20160, + + /* + |-------------------------------------------------------------------------- + | JWT hashing algorithm + |-------------------------------------------------------------------------- + | + | Specify the hashing algorithm that will be used to sign the token. + | + | See here: https://github.com/namshi/jose/tree/2.2.0/src/Namshi/JOSE/Signer + | for possible values + | + */ + + 'algo' => 'HS256', + + /* + |-------------------------------------------------------------------------- + | User Model namespace + |-------------------------------------------------------------------------- + | + | Specify the full namespace to your User model. + | e.g. 'Acme\Entities\User' + | + */ + + 'user' => 'App\User', + + /* + |-------------------------------------------------------------------------- + | User identifier + |-------------------------------------------------------------------------- + | + | Specify a unique property of the user that will be added as the 'sub' + | claim of the token payload. + | + */ + + 'identifier' => 'id', + + /* + |-------------------------------------------------------------------------- + | Required Claims + |-------------------------------------------------------------------------- + | + | Specify the required claims that must exist in any token. + | A TokenInvalidException will be thrown if any of these claims are not + | present in the payload. + | + */ + + 'required_claims' => ['iss', 'iat', 'exp', 'nbf', 'sub', 'jti'], + + /* + |-------------------------------------------------------------------------- + | Blacklist Enabled + |-------------------------------------------------------------------------- + | + | In order to invalidate tokens, you must have the blacklist enabled. + | If you do not want or need this functionality, then set this to false. + | + */ + + 'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true), + + /* + |-------------------------------------------------------------------------- + | Providers + |-------------------------------------------------------------------------- + | + | Specify the various providers used throughout the package. + | + */ + + 'providers' => [ + + /* + |-------------------------------------------------------------------------- + | User Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to find the user based + | on the subject claim + | + */ + + 'user' => 'Tymon\JWTAuth\Providers\User\EloquentUserAdapter', + + /* + |-------------------------------------------------------------------------- + | JWT Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to create and decode the tokens. + | + */ + + 'jwt' => 'Tymon\JWTAuth\Providers\JWT\NamshiAdapter', + + /* + |-------------------------------------------------------------------------- + | Authentication Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to authenticate users. + | + */ + + 'auth' => 'Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter', + + /* + |-------------------------------------------------------------------------- + | Storage Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to store tokens in the blacklist + | + */ + + 'storage' => 'Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter', + + ], + +]; diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/BlacklistTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/BlacklistTest.php new file mode 100644 index 0000000..0f00881 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/BlacklistTest.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test\Providers\JWT; + +use Mockery; +use Carbon\Carbon; +use Tymon\JWTAuth\Payload; +use Tymon\JWTAuth\Blacklist; +use Tymon\JWTAuth\Claims\JwtId; +use Tymon\JWTAuth\Claims\Issuer; +use Tymon\JWTAuth\Claims\Subject; +use Tymon\JWTAuth\Claims\IssuedAt; +use Tymon\JWTAuth\Claims\NotBefore; +use Tymon\JWTAuth\Claims\Expiration; + +class BlacklistTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + Carbon::setTestNow(Carbon::createFromTimeStampUTC(123)); + + $this->storage = Mockery::mock('Tymon\JWTAuth\Providers\Storage\StorageInterface'); + $this->blacklist = new Blacklist($this->storage); + $this->blacklist->setRefreshTTL(20160); + + $this->validator = Mockery::mock('Tymon\JWTAuth\Validators\PayloadValidator'); + $this->validator->shouldReceive('setRefreshFlow->check'); + } + + public function tearDown() + { + Mockery::close(); + } + + /** @test */ + public function it_should_add_a_valid_token_to_the_blacklist() + { + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(100 + 3600), + new NotBefore(100), + new IssuedAt(100), + new JwtId('foo'), + ]; + $payload = new Payload($claims, $this->validator); + + $this->storage->shouldReceive('add')->once()->with('foo', [], 20160); + $this->assertTrue($this->blacklist->add($payload)); + } + + /** @test */ + public function it_should_return_true_when_adding_a_refreshable_expired_token_to_the_blacklist() + { + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(101), + new NotBefore(100), + new IssuedAt(100), + new JwtId('foo'), + ]; + $payload = new Payload($claims, $this->validator, true); + + $this->storage->shouldReceive('add')->once()->with('foo', [], 20160); + $this->assertTrue($this->blacklist->add($payload)); + } + + /** @test */ + public function it_should_return_false_when_adding_an_unrefreshable_token_to_the_blacklist() + { + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(100), // default refresh_ttl + new NotBefore(100), + new IssuedAt(100 - 20160 * 60), + new JwtId('foo'), + ]; + $payload = new Payload($claims, $this->validator, true); + + $this->storage->shouldReceive('add')->never(); + $this->assertFalse($this->blacklist->add($payload)); + } + + /** @test */ + public function it_should_return_false_when_adding_a_unrefreshable_token_after_modifying_refresh_ttl() + { + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(101), + new NotBefore(100), + new IssuedAt(100), + new JwtId('foo'), + ]; + $payload = new Payload($claims, $this->validator, true); + + $this->storage->shouldReceive('add')->never(); + $this->blacklist->setRefreshTTL(0); + $this->assertFalse($this->blacklist->add($payload)); + } + + /** @test */ + public function it_should_check_whether_a_token_has_been_blacklisted() + { + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(123 + 3600), + new NotBefore(123), + new IssuedAt(123), + new JwtId('foobar'), + ]; + $payload = new Payload($claims, $this->validator); + + $this->storage->shouldReceive('has')->once()->with('foobar')->andReturn(true); + $this->assertTrue($this->blacklist->has($payload)); + } + + /** @test */ + public function it_should_remove_a_token_from_the_blacklist() + { + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(123 + 3600), + new NotBefore(123), + new IssuedAt(123), + new JwtId('foobar'), + ]; + $payload = new Payload($claims, $this->validator); + + $this->storage->shouldReceive('destroy')->once()->with('foobar')->andReturn(true); + $this->assertTrue($this->blacklist->remove($payload)); + } + + /** @test */ + public function it_should_empty_the_blacklist() + { + $this->storage->shouldReceive('flush')->once(); + $this->assertTrue($this->blacklist->clear()); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Commands/JWTGenerateCommandTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Commands/JWTGenerateCommandTest.php new file mode 100644 index 0000000..a4a11ac --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Commands/JWTGenerateCommandTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test; + +use Illuminate\Foundation\Application; +use Tymon\JWTAuth\Commands\JWTGenerateCommand; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\NullOutput; +use Symfony\Component\Console\Tester\CommandTester; + +class JWTGenerateCommandTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->command = new JWTGenerateCommand(); + $this->tester = new CommandTester($this->command); + } + + /** @test */ + public function it_shoud_generate_random_key() + { + // $app = new Application(); + + // $app['path.base'] = ''; + + // $this->command->setLaravel($app); + + // $this->runCommand($this->command); + } + + protected function runCommand($command, $input = []) + { + return $command->run(new ArrayInput($input), new NullOutput); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/JWTAuthTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/JWTAuthTest.php new file mode 100644 index 0000000..3f910d4 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/JWTAuthTest.php @@ -0,0 +1,235 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test; + +use Mockery; +use Tymon\JWTAuth\Token; +use Tymon\JWTAuth\JWTAuth; +use Illuminate\Http\Request; + +class JWTAuthTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->user = Mockery::mock('Tymon\JWTAuth\Providers\User\UserInterface'); + $this->manager = Mockery::mock('Tymon\JWTAuth\JWTManager'); + $this->auth = Mockery::mock('Tymon\JWTAuth\Providers\Auth\AuthInterface'); + + $this->jwtAuth = new JWTAuth($this->manager, $this->user, $this->auth, Request::create('/foo', 'GET')); + } + + public function tearDown() + { + Mockery::close(); + } + + /** @test */ + public function it_should_return_a_user_when_passing_a_token_containing_a_valid_subject_claim() + { + $payload = Mockery::mock('Tymon\JWTAuth\Payload'); + $payload->shouldReceive('offsetGet')->once()->andReturn(1); + + $this->manager->shouldReceive('decode')->once()->andReturn($payload); + $this->user->shouldReceive('getBy')->once()->andReturn((object) ['id' => 1]); + + $user = $this->jwtAuth->toUser('foo.bar.baz'); + + $this->assertEquals(1, $user->id); + } + + /** @test */ + public function it_should_return_false_when_passing_a_token_containing_an_invalid_subject_claim() + { + $payload = Mockery::mock('Tymon\JWTAuth\Payload'); + $payload->shouldReceive('offsetGet')->once()->andReturn(1); + + $this->manager->shouldReceive('decode')->once()->andReturn($payload); + $this->user->shouldReceive('getBy')->once()->andReturn(false); + + $user = $this->jwtAuth->toUser('foo.bar.baz'); + + $this->assertFalse($user); + } + + /** @test */ + public function it_should_return_a_token_when_passing_a_user() + { + $this->manager->shouldReceive('getPayloadFactory->make')->once()->andReturn(Mockery::mock('Tymon\JWTAuth\Payload')); + $this->manager->shouldReceive('encode->get')->once()->andReturn('foo.bar.baz'); + + $token = $this->jwtAuth->fromUser((object) ['id' => 1]); + + $this->assertEquals($token, 'foo.bar.baz'); + } + + /** @test */ + public function it_should_return_a_token_when_passing_valid_credentials_to_attempt_method() + { + $this->manager->shouldReceive('getPayloadFactory->make')->once()->andReturn(Mockery::mock('Tymon\JWTAuth\Payload')); + $this->manager->shouldReceive('encode->get')->once()->andReturn('foo.bar.baz'); + + $this->auth->shouldReceive('byCredentials')->once()->andReturn(true); + $this->auth->shouldReceive('user')->once()->andReturn((object) ['id' => 1]); + + $token = $this->jwtAuth->attempt(); + + $this->assertEquals($token, 'foo.bar.baz'); + } + + /** @test */ + public function it_should_return_false_when_passing_invalid_credentials_to_attempt_method() + { + $this->manager->shouldReceive('encode->get')->never(); + $this->auth->shouldReceive('byCredentials')->once()->andReturn(false); + $this->auth->shouldReceive('user')->never(); + + $token = $this->jwtAuth->attempt(); + + $this->assertFalse($token); + } + + /** @test */ + public function it_should_throw_an_exception_when_not_providing_a_token() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\JWTException'); + + $this->jwtAuth->toUser(); + } + + /** @test */ + public function it_should_return_the_owning_user_from_a_token_containing_an_existing_user() + { + $payload = Mockery::mock('Tymon\JWTAuth\Payload'); + $payload->shouldReceive('get')->once()->with('sub')->andReturn(1); + + $this->manager->shouldReceive('decode')->once()->andReturn($payload); + + $this->auth->shouldReceive('byId')->once()->with(1)->andReturn(true); + $this->auth->shouldReceive('user')->once()->andReturn((object) ['id' => 1]); + + $user = $this->jwtAuth->authenticate('foo.bar.baz'); + + $this->assertEquals($user->id, 1); + } + + /** @test */ + public function it_should_return_false_when_passing_a_token_not_containing_an_existing_user() + { + $payload = Mockery::mock('Tymon\JWTAuth\Payload'); + $payload->shouldReceive('get')->once()->with('sub')->andReturn(1); + + $this->manager->shouldReceive('decode')->once()->andReturn($payload); + + $this->auth->shouldReceive('byId')->once()->with(1)->andReturn(false); + $this->auth->shouldReceive('user')->never(); + + $user = $this->jwtAuth->authenticate('foo.bar.baz'); + + $this->assertFalse($user); + } + + /** @test */ + public function it_should_refresh_a_token() + { + $newToken = Mockery::mock('Tymon\JWTAuth\Token'); + $newToken->shouldReceive('get')->once()->andReturn('baz.bar.foo'); + + $this->manager->shouldReceive('refresh')->once()->andReturn($newToken); + + $result = $this->jwtAuth->setToken('foo.bar.baz')->refresh(); + + $this->assertEquals($result, 'baz.bar.foo'); + } + + /** @test */ + public function it_should_invalidate_a_token() + { + $this->manager->shouldReceive('invalidate')->once()->andReturn(true); + + $result = $this->jwtAuth->invalidate('foo.bar.baz'); + + $this->assertTrue($result); + } + + /** @test */ + public function it_should_retrieve_the_token_from_the_auth_header() + { + $request = Request::create('/foo', 'GET'); + $request->headers->set('authorization', 'Bearer foo.bar.baz'); + $jwtAuth = new JWTAuth($this->manager, $this->user, $this->auth, $request); + + $this->assertInstanceOf('Tymon\JWTAuth\Token', $jwtAuth->parseToken()->getToken()); + $this->assertEquals($jwtAuth->getToken(), 'foo.bar.baz'); + } + + /** @test */ + public function it_should_retrieve_the_token_from_the_query_string() + { + $request = Request::create('/foo', 'GET', ['token' => 'foo.bar.baz']); + $jwtAuth = new JWTAuth($this->manager, $this->user, $this->auth, $request); + + $this->assertInstanceOf('Tymon\JWTAuth\Token', $jwtAuth->parseToken()->getToken()); + $this->assertEquals($jwtAuth->getToken(), 'foo.bar.baz'); + } + + /** @test */ + public function it_should_throw_an_exception_when_token_not_present_in_request() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\JWTException'); + + $request = Request::create('/foo', 'GET'); + $jwtAuth = new JWTAuth($this->manager, $this->user, $this->auth, $request); + + $jwtAuth->parseToken(); + } + + /** @test */ + public function it_should_return_false_when_no_token_is_set() + { + $this->assertFalse($this->jwtAuth->getToken()); + } + + /** @test */ + public function it_should_set_the_identifier() + { + $this->jwtAuth->setIdentifier('foo'); + + $this->assertEquals($this->jwtAuth->getIdentifier(), 'foo'); + } + + /** @test */ + public function it_should_magically_call_the_manager() + { + $this->manager->shouldReceive('getBlacklist')->andReturn(new \StdClass); + + $blacklist = $this->jwtAuth->getBlacklist(); + + $this->assertInstanceOf('StdClass', $blacklist); + } + + /** @test */ + public function it_should_set_the_request() + { + $request = Request::create('/foo', 'GET', ['token' => 'some.random.token']); + + $token = $this->jwtAuth->setRequest($request)->getToken(); + + $this->assertEquals('some.random.token', $token); + } + + /** @test */ + public function it_should_get_the_manager_instance() + { + $manager = $this->jwtAuth->manager(); + $this->assertInstanceOf('Tymon\JWTAuth\JWTManager', $manager); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/JWTManagerTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/JWTManagerTest.php new file mode 100644 index 0000000..e3ad97d --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/JWTManagerTest.php @@ -0,0 +1,188 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test\Providers\JWT; + +use Mockery; +use Tymon\JWTAuth\Token; +use Tymon\JWTAuth\Payload; +use Tymon\JWTAuth\JWTManager; +use Tymon\JWTAuth\Claims\JwtId; +use Tymon\JWTAuth\Claims\Issuer; +use Tymon\JWTAuth\Claims\Subject; +use Tymon\JWTAuth\Claims\IssuedAt; +use Tymon\JWTAuth\Claims\NotBefore; +use Tymon\JWTAuth\Claims\Expiration; + +class JWTManagerTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->jwt = Mockery::mock('Tymon\JWTAuth\Providers\JWT\JWTInterface'); + $this->blacklist = Mockery::mock('Tymon\JWTAuth\Blacklist'); + $this->factory = Mockery::mock('Tymon\JWTAuth\PayloadFactory'); + $this->manager = new JWTManager($this->jwt, $this->blacklist, $this->factory); + + $this->validator = Mockery::mock('Tymon\JWTAuth\Validators\PayloadValidator'); + $this->validator->shouldReceive('setRefreshFlow->check'); + } + + public function tearDown() + { + Mockery::close(); + } + + /** @test */ + public function it_should_encode_a_payload() + { + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(123 + 3600), + new NotBefore(123), + new IssuedAt(123), + new JwtId('foo'), + ]; + $payload = new Payload($claims, $this->validator); + + $this->jwt->shouldReceive('encode')->with($payload->toArray())->andReturn('foo.bar.baz'); + + $token = $this->manager->encode($payload); + + $this->assertEquals($token, 'foo.bar.baz'); + } + + /** @test */ + public function it_should_decode_a_token() + { + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(123 + 3600), + new NotBefore(123), + new IssuedAt(123), + new JwtId('foo'), + ]; + $payload = new Payload($claims, $this->validator); + $token = new Token('foo.bar.baz'); + + $this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray()); + $this->factory->shouldReceive('setRefreshFlow->make')->with($payload->toArray())->andReturn($payload); + $this->blacklist->shouldReceive('has')->with($payload)->andReturn(false); + + $payload = $this->manager->decode($token); + + $this->assertInstanceOf('Tymon\JWTAuth\Payload', $payload); + } + + /** @test */ + public function it_should_throw_exception_when_token_is_blacklisted() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenBlacklistedException'); + + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(123 + 3600), + new NotBefore(123), + new IssuedAt(123), + new JwtId('foo'), + ]; + $payload = new Payload($claims, $this->validator); + $token = new Token('foo.bar.baz'); + + $this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray()); + $this->factory->shouldReceive('setRefreshFlow->make')->with($payload->toArray())->andReturn($payload); + $this->blacklist->shouldReceive('has')->with($payload)->andReturn(true); + + $this->manager->decode($token); + } + + /** @test */ + public function it_should_refresh_a_token() + { + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(123 - 3600), + new NotBefore(123), + new IssuedAt(123), + new JwtId('foo'), + ]; + $payload = new Payload($claims, $this->validator, true); + $token = new Token('foo.bar.baz'); + + $this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray()); + $this->jwt->shouldReceive('encode')->with($payload->toArray())->andReturn('baz.bar.foo'); + + $this->factory->shouldReceive('setRefreshFlow')->andReturn($this->factory); + $this->factory->shouldReceive('make')->andReturn($payload); + + $this->blacklist->shouldReceive('has')->with($payload)->andReturn(false); + $this->blacklist->shouldReceive('add')->once()->with($payload); + + $token = $this->manager->refresh($token); + + $this->assertInstanceOf('Tymon\JWTAuth\Token', $token); + $this->assertEquals('baz.bar.foo', $token); + } + + /** @test */ + public function it_should_invalidate_a_token() + { + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(123 + 3600), + new NotBefore(123), + new IssuedAt(123), + new JwtId('foo'), + ]; + $payload = new Payload($claims, $this->validator); + $token = new Token('foo.bar.baz'); + + $this->jwt->shouldReceive('decode')->once()->with('foo.bar.baz')->andReturn($payload->toArray()); + $this->factory->shouldReceive('setRefreshFlow->make')->with($payload->toArray())->andReturn($payload); + $this->blacklist->shouldReceive('has')->with($payload)->andReturn(false); + + $this->blacklist->shouldReceive('add')->with($payload)->andReturn(true); + + $this->manager->invalidate($token); + } + + /** @test */ + public function it_should_throw_an_exception_when_enable_blacklist_is_set_to_false() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\JWTException'); + + $token = new Token('foo.bar.baz'); + + $this->manager->setBlacklistEnabled(false)->invalidate($token); + } + + /** @test */ + public function it_should_get_the_payload_factory() + { + $this->assertInstanceOf('Tymon\JWTAuth\PayloadFactory', $this->manager->getPayloadFactory()); + } + + /** @test */ + public function it_should_get_the_jwt_provider() + { + $this->assertInstanceOf('Tymon\JWTAuth\Providers\JWT\JWTInterface', $this->manager->getJWTProvider()); + } + + /** @test */ + public function it_should_get_the_blacklist() + { + $this->assertInstanceOf('Tymon\JWTAuth\Blacklist', $this->manager->getBlacklist()); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Middleware/GetUserFromTokenTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Middleware/GetUserFromTokenTest.php new file mode 100644 index 0000000..afb18ea --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Middleware/GetUserFromTokenTest.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test; + +use Mockery; +use Tymon\JWTAuth\Middleware\GetUserFromToken; +use Tymon\JWTAuth\Exceptions\TokenExpiredException; +use Tymon\JWTAuth\Exceptions\TokenInvalidException; + +class GetUserFromTokenTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->events = Mockery::mock('Illuminate\Contracts\Events\Dispatcher'); + $this->auth = Mockery::mock('Tymon\JWTAuth\JWTAuth'); + + $this->request = Mockery::mock('Illuminate\Http\Request'); + $this->response = Mockery::mock('Illuminate\Contracts\Routing\ResponseFactory'); + + $this->middleware = new GetUserFromToken($this->response, $this->events, $this->auth); + + $this->auth->shouldReceive('setRequest')->once()->with($this->request)->andReturn($this->auth); + } + + public function tearDown() + { + Mockery::close(); + } + + /** @test */ + public function it_should_fire_an_event_when_no_token_is_available() + { + $this->auth->shouldReceive('getToken')->once()->andReturn(false); + + $this->events->shouldReceive('fire')->once()->with('tymon.jwt.absent', [], true); + $this->response->shouldReceive('json')->with(['error' => 'token_not_provided'], 400); + + $this->middleware->handle($this->request, function () { + }); + } + + /** @test */ + public function it_should_fire_an_event_when_the_token_has_expired() + { + $exception = new TokenExpiredException; + + $this->auth->shouldReceive('getToken')->once()->andReturn('foo'); + $this->auth->shouldReceive('authenticate')->once()->with('foo')->andThrow($exception); + + $this->events->shouldReceive('fire')->once()->with('tymon.jwt.expired', [$exception], true); + $this->response->shouldReceive('json')->with(['error' => 'token_expired'], 401); + + $this->middleware->handle($this->request, function () { + }); + } + + /** @test */ + public function it_should_fire_an_event_when_the_token_is_invalid() + { + $exception = new TokenInvalidException; + + $this->auth->shouldReceive('getToken')->once()->andReturn('foo'); + $this->auth->shouldReceive('authenticate')->once()->with('foo')->andThrow($exception); + + $this->events->shouldReceive('fire')->once()->with('tymon.jwt.invalid', [$exception], true); + $this->response->shouldReceive('json')->with(['error' => 'token_invalid'], 400); + + $this->middleware->handle($this->request, function () { + }); + } + + /** @test */ + public function it_should_fire_an_event_when_no_user_is_found() + { + $this->auth->shouldReceive('getToken')->once()->andReturn('foo'); + $this->auth->shouldReceive('authenticate')->once()->with('foo')->andReturn(false); + + $this->events->shouldReceive('fire')->once()->with('tymon.jwt.user_not_found', [], true); + $this->response->shouldReceive('json')->with(['error' => 'user_not_found'], 404); + + $this->middleware->handle($this->request, function () { + }); + } + + /** @test */ + public function it_should_fire_an_event_when_the_token_has_been_decoded_and_user_is_found() + { + $user = (object) ['id' => 1]; + + $this->auth->shouldReceive('getToken')->once()->andReturn('foo'); + $this->auth->shouldReceive('authenticate')->once()->with('foo')->andReturn($user); + + $this->events->shouldReceive('fire')->once()->with('tymon.jwt.valid', $user); + $this->response->shouldReceive('json')->never(); + + $this->middleware->handle($this->request, function () { + }); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/PayloadFactoryTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/PayloadFactoryTest.php new file mode 100644 index 0000000..f25d6cc --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/PayloadFactoryTest.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test\Providers\JWT; + +use Mockery; +use Carbon\Carbon; +use Illuminate\Http\Request; +use Tymon\JWTAuth\Claims\JwtId; +use Tymon\JWTAuth\Claims\Custom; +use Tymon\JWTAuth\Claims\Issuer; +use Tymon\JWTAuth\Claims\Subject; +use Tymon\JWTAuth\PayloadFactory; +use Tymon\JWTAuth\Claims\IssuedAt; +use Tymon\JWTAuth\Claims\NotBefore; +use Tymon\JWTAuth\Claims\Expiration; + +class PayloadFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + Carbon::setTestNow(Carbon::createFromTimeStampUTC(123)); + + $this->claimFactory = Mockery::mock('Tymon\JWTAuth\Claims\Factory'); + $this->validator = Mockery::mock('Tymon\JWTAuth\Validators\PayloadValidator'); + $this->factory = new PayloadFactory($this->claimFactory, Request::create('/foo', 'GET'), $this->validator); + } + + public function tearDown() + { + Mockery::close(); + } + + /** @test */ + public function it_should_return_a_payload_when_passing_an_array_of_claims_to_make_method() + { + $this->validator->shouldReceive('setRefreshFlow->check'); + + $expTime = 123 + 3600; + + $this->claimFactory->shouldReceive('get')->once()->with('sub', 1)->andReturn(new Subject(1)); + $this->claimFactory->shouldReceive('get')->once()->with('iss', Mockery::any())->andReturn(new Issuer('/foo')); + $this->claimFactory->shouldReceive('get')->once()->with('iat', 123)->andReturn(new IssuedAt(123)); + $this->claimFactory->shouldReceive('get')->once()->with('jti', 'foo')->andReturn(new JwtId('foo')); + $this->claimFactory->shouldReceive('get')->once()->with('nbf', 123)->andReturn(new NotBefore(123)); + $this->claimFactory->shouldReceive('get')->once()->with('exp', $expTime)->andReturn(new Expiration($expTime)); + + $payload = $this->factory->make(['sub' => 1, 'jti' => 'foo', 'iat' => 123]); + + $this->assertEquals($payload->get('sub'), 1); + $this->assertEquals($payload->get('iat'), 123); + $this->assertEquals($payload['exp'], $expTime); + + $this->assertInstanceOf('Tymon\JWTAuth\Payload', $payload); + } + + /** @test **/ + public function it_should_check_custom_claim_keys_accurately_and_accept_numeric_claims() + { + $this->validator->shouldReceive('setRefreshFlow->check'); + + $this->claimFactory->shouldReceive('get')->once()->with('iss', Mockery::any())->andReturn(new Issuer('/foo')); + $this->claimFactory->shouldReceive('get')->once()->with('exp', 123 + 3600)->andReturn(new Expiration(123 + 3600)); + $this->claimFactory->shouldReceive('get')->once()->with('iat', 123)->andReturn(new IssuedAt(123)); + $this->claimFactory->shouldReceive('get')->once()->with('jti', Mockery::any())->andReturn(new JwtId('foo')); + $this->claimFactory->shouldReceive('get')->once()->with('nbf', 123)->andReturn(new NotBefore(123)); + $this->claimFactory->shouldReceive('get')->once()->with(1, 'claim one')->andReturn(new Custom(1, 'claim one')); + + $payload = $this->factory->make([1 => 'claim one']); + + // if the checker doesn't compare defaults properly, numeric-keyed claims might be ignored + $this->assertEquals('claim one', $payload->get(1)); + // iat is $defaultClaims[1], so verify it wasn't skipped due to a bad k-v comparison + $this->assertEquals(123, $payload->get('iat')); + } + + /** @test */ + public function it_should_return_a_payload_when_chaining_claim_methods() + { + $this->validator->shouldReceive('setRefreshFlow->check'); + + $this->claimFactory->shouldReceive('get')->once()->with('sub', 1)->andReturn(new Subject(1)); + $this->claimFactory->shouldReceive('get')->once()->with('iss', Mockery::any())->andReturn(new Issuer('/foo')); + $this->claimFactory->shouldReceive('get')->once()->with('exp', 123 + 3600)->andReturn(new Expiration(123 + 3600)); + $this->claimFactory->shouldReceive('get')->once()->with('iat', 123)->andReturn(new IssuedAt(123)); + $this->claimFactory->shouldReceive('get')->once()->with('jti', Mockery::any())->andReturn(new JwtId('foo')); + $this->claimFactory->shouldReceive('get')->once()->with('nbf', 123)->andReturn(new NotBefore(123)); + $this->claimFactory->shouldReceive('get')->once()->with('foo', 'baz')->andReturn(new Custom('foo', 'baz')); + + $payload = $this->factory->sub(1)->foo('baz')->make(); + + $this->assertEquals($payload['sub'], 1); + $this->assertEquals($payload->get('jti'), 'foo'); + $this->assertEquals($payload->get('foo'), 'baz'); + + $this->assertInstanceOf('Tymon\JWTAuth\Payload', $payload); + } + + /** @test */ + public function it_should_return_a_payload_when_passing_miltidimensional_claims() + { + $this->validator->shouldReceive('setRefreshFlow->check'); + $userObject = ['name' => 'example']; + + $this->claimFactory->shouldReceive('get')->once()->with('sub', $userObject)->andReturn(new Subject($userObject)); + $this->claimFactory->shouldReceive('get')->once()->with('iss', Mockery::any())->andReturn(new Issuer('/foo')); + $this->claimFactory->shouldReceive('get')->once()->with('exp', Mockery::any())->andReturn(new Expiration(123 + 3600)); + $this->claimFactory->shouldReceive('get')->once()->with('iat', Mockery::any())->andReturn(new IssuedAt(123)); + $this->claimFactory->shouldReceive('get')->once()->with('jti', Mockery::any())->andReturn(new JwtId('foo')); + $this->claimFactory->shouldReceive('get')->once()->with('nbf', Mockery::any())->andReturn(new NotBefore(123)); + $this->claimFactory->shouldReceive('get')->once()->with('foo', ['bar' => [0, 0, 0]])->andReturn(new Custom('foo', ['bar' => [0, 0, 0]])); + + $payload = $this->factory->sub($userObject)->foo(['bar' => [0, 0, 0]])->make(); + + $this->assertEquals($payload->get('sub'), $userObject); + $this->assertEquals($payload->get('foo'), ['bar' => [0, 0, 0]]); + + $this->assertInstanceOf('Tymon\JWTAuth\Payload', $payload); + } + + /** @test */ + public function it_should_set_the_ttl() + { + $this->factory->setTTL(12345); + + $this->assertEquals($this->factory->getTTL(), 12345); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/PayloadTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/PayloadTest.php new file mode 100644 index 0000000..42ae69b --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/PayloadTest.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test\Providers\JWT; + +use Mockery; +use Carbon\Carbon; +use Tymon\JWTAuth\Payload; +use Tymon\JWTAuth\Claims\JwtId; +use Tymon\JWTAuth\Claims\Issuer; +use Tymon\JWTAuth\Claims\Subject; +use Tymon\JWTAuth\Claims\Audience; +use Tymon\JWTAuth\Claims\IssuedAt; +use Tymon\JWTAuth\Claims\NotBefore; +use Tymon\JWTAuth\Claims\Expiration; + +class PayloadTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + Carbon::setTestNow(Carbon::createFromTimeStampUTC(123)); + + $claims = [ + new Subject(1), + new Issuer('http://example.com'), + new Expiration(123 + 3600), + new NotBefore(123), + new IssuedAt(123), + new JwtId('foo'), + ]; + + $this->validator = Mockery::mock('Tymon\JWTAuth\Validators\PayloadValidator'); + $this->validator->shouldReceive('setRefreshFlow->check'); + + $this->payload = new Payload($claims, $this->validator); + } + + public function tearDown() + { + Mockery::close(); + } + + /** @test */ + public function it_throws_an_exception_when_trying_to_add_to_the_payload() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\PayloadException'); + + $this->payload['foo'] = 'bar'; + } + + /** @test */ + public function it_throws_an_exception_when_trying_to_remove_a_key_from_the_payload() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\PayloadException'); + + unset($this->payload['foo']); + } + + /** @test */ + public function it_should_cast_the_payload_to_a_string_as_json() + { + $this->assertEquals((string) $this->payload, json_encode($this->payload->get())); + $this->assertJsonStringEqualsJsonString((string) $this->payload, json_encode($this->payload->get())); + } + + /** @test */ + public function it_should_allow_array_access_on_the_payload() + { + $this->assertTrue(isset($this->payload['iat'])); + $this->assertEquals($this->payload['sub'], 1); + $this->assertArrayHasKey('exp', $this->payload); + } + + /** @test */ + public function it_should_get_properties_of_payload_via_get_method() + { + $this->assertInternalType('array', $this->payload->get()); + $this->assertEquals($this->payload->get('sub'), 1); + } + + /** @test */ + public function it_should_get_multiple_properties_when_passing_an_array_to_the_get_method() + { + $values = $this->payload->get(['sub', 'jti']); + + list($sub, $jti) = $values; + + $this->assertInternalType('array', $values); + $this->assertEquals($sub, 1); + $this->assertEquals($jti, 'foo'); + } + + /** @test */ + public function it_should_determine_whether_the_payload_has_a_claim() + { + $this->assertTrue($this->payload->has(new Subject(1))); + $this->assertFalse($this->payload->has(new Audience(1))); + } + + /** @test */ + public function it_should_magically_get_a_property() + { + $sub = $this->payload->getSubject(); + $jti = $this->payload->getJwtId(); + $iss = $this->payload->getIssuer(); + + $this->assertEquals($sub, 1); + $this->assertEquals($jti, 'foo'); + $this->assertEquals($iss, 'http://example.com'); + } + + /** @test */ + public function it_should_throw_an_exception_when_magically_getting_a_property_that_does_not_exist() + { + $this->setExpectedException('\BadMethodCallException'); + + $this->payload->getFoo(); + } + + /** @test */ + public function it_should_get_the_claims() + { + $claims = $this->payload->getClaims(); + + $this->assertInstanceOf('Tymon\JWTAuth\Claims\Expiration', $claims[2]); + $this->assertInstanceOf('Tymon\JWTAuth\Claims\JwtId', $claims[5]); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/Auth/IlluminateAuthAdapterTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/Auth/IlluminateAuthAdapterTest.php new file mode 100644 index 0000000..3230dcc --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/Auth/IlluminateAuthAdapterTest.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test\Providers\Auth; + +use Mockery; +use Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter; + +class IlluminateAuthAdapterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->authManager = Mockery::mock('Illuminate\Auth\AuthManager'); + $this->auth = new IlluminateAuthAdapter($this->authManager); + } + + public function tearDown() + { + Mockery::close(); + } + + /** @test */ + public function it_should_return_true_if_credentials_are_valid() + { + $this->authManager->shouldReceive('once')->once()->with(['email' => 'foo@bar.com', 'password' => 'foobar'])->andReturn(true); + $this->assertTrue($this->auth->byCredentials(['email' => 'foo@bar.com', 'password' => 'foobar'])); + } + + /** @test */ + public function it_should_return_true_if_user_is_found() + { + $this->authManager->shouldReceive('onceUsingId')->once()->with(123)->andReturn(true); + $this->assertTrue($this->auth->byId(123)); + } + + /** @test */ + public function it_should_return_false_if_user_is_not_found() + { + $this->authManager->shouldReceive('onceUsingId')->once()->with(123)->andReturn(false); + $this->assertFalse($this->auth->byId(123)); + } + + /** @test */ + public function it_should_bubble_exceptions_from_auth() + { + $this->authManager->shouldReceive('onceUsingId')->once()->with(123)->andThrow(new \Exception('Some auth failure')); + $this->setExpectedException('Exception', 'Some auth failure'); + $this->auth->byId(123); + } + + /** @test */ + public function it_should_return_the_currently_authenticated_user() + { + $this->authManager->shouldReceive('user')->once()->andReturn((object) ['id' => 1]); + $this->assertEquals($this->auth->user()->id, 1); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/JWT/JWTProviderTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/JWT/JWTProviderTest.php new file mode 100644 index 0000000..227afdb --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/JWT/JWTProviderTest.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test\Providers\JWT; + +use Mockery; +use Tymon\JWTAuth\Test\Stubs\JWTProviderStub; + +class JWTProviderTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->provider = new JWTProviderStub('secret', 'HS256'); + } + + public function tearDown() + { + Mockery::close(); + } + + /** @test */ + public function it_should_set_the_algo() + { + $this->provider->setAlgo('HS512'); + + $this->assertEquals('HS512', $this->provider->getAlgo()); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/JWT/NamshiAdapterTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/JWT/NamshiAdapterTest.php new file mode 100644 index 0000000..2f4be91 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/JWT/NamshiAdapterTest.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test\Providers\JWT; + +use Mockery; +use Carbon\Carbon; +use Tymon\JWTAuth\Providers\JWT\NamshiAdapter; + +class NamshiAdapterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + Carbon::setTestNow(Carbon::createFromTimeStampUTC(123)); + + $this->jws = Mockery::mock('Namshi\JOSE\JWS'); + $this->provider = new NamshiAdapter('secret', 'HS256', $this->jws); + } + + public function tearDown() + { + Mockery::close(); + } + + /** @test */ + public function it_should_return_the_token_when_passing_a_valid_subject_to_encode() + { + $payload = ['sub' => 1, 'exp' => 123, 'iat' => 123, 'iss' => '/foo']; + + $this->jws->shouldReceive('setPayload')->once()->with($payload)->andReturn(Mockery::self()); + $this->jws->shouldReceive('sign')->once()->with('secret')->andReturn(Mockery::self()); + $this->jws->shouldReceive('getTokenString')->once()->andReturn('foo.bar.baz'); + + $token = $this->provider->encode($payload); + + $this->assertEquals('foo.bar.baz', $token); + } + + /** @test */ + public function it_should_throw_an_invalid_exception_when_the_payload_could_not_be_encoded() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\JWTException'); + + $this->jws->shouldReceive('sign')->andThrow(new \Exception); + + $payload = ['sub' => 1, 'exp' => 123, 'iat' => 123, 'iss' => '/foo']; + $this->provider->encode($payload); + } + + /** @test */ + // public function it_should_return_the_payload_when_passing_a_valid_token_to_decode() + // { + // $this->jws->shouldReceive('load')->once()->with('foo.bar.baz')->andReturn(true); + // $this->jws->shouldReceive('verify')->andReturn(true); + + // $payload = $this->provider->decode('foo.bar.baz'); + + // } + + /** @test */ + public function it_should_throw_a_token_invalid_exception_when_the_token_could_not_be_decoded() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException'); + + $this->jws->shouldReceive('verify')->andReturn(false); + + $token = $this->provider->decode('foo'); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/Storage/IlluminateCacheAdapterTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/Storage/IlluminateCacheAdapterTest.php new file mode 100644 index 0000000..26bc40f --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/Storage/IlluminateCacheAdapterTest.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test\Providers\Storage; + +use Mockery; +use Tymon\JWTAuth\Providers\Storage\IlluminateCacheAdapter; + +class IlluminateCacheAdapterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->cache = Mockery::mock('Illuminate\Cache\CacheManager'); + $this->storage = new IlluminateCacheAdapter($this->cache); + + $this->cache->shouldReceive('tags')->andReturn(Mockery::self()); + } + + public function tearDown() + { + Mockery::close(); + } + + /** @test */ + public function it_should_add_the_item_to_storage() + { + $this->cache->shouldReceive('tags->put')->with('foo', 'bar', 10); + + $this->storage->add('foo', 'bar', 10); + } + + /** @test */ + public function it_should_check_if_the_item_exists_in_storage() + { + $this->cache->shouldReceive('tags->has')->with('foo')->andReturn(true); + + $this->assertTrue($this->storage->has('foo')); + } + + /** @test */ + public function it_should_remove_the_item_from_storage() + { + $this->cache->shouldReceive('tags->forget')->with('foo')->andReturn(true); + + $this->assertTrue($this->storage->destroy('foo')); + } + + /** @test */ + public function it_should_remove_all_items_from_storage() + { + $this->cache->shouldReceive('tags->flush')->withNoArgs(); + + $this->storage->flush(); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/User/EloquentUserAdapterTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/User/EloquentUserAdapterTest.php new file mode 100644 index 0000000..233a377 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Providers/User/EloquentUserAdapterTest.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test\Providers\User; + +use Mockery; +use Tymon\JWTAuth\Providers\User\EloquentUserAdapter; + +class EloquentUserAdapterTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->builder = Mockery::mock('Illuminate\Database\Query\Builder'); + $this->model = Mockery::mock('Illuminate\Database\Eloquent\Model'); + $this->user = new EloquentUserAdapter($this->model); + } + + public function tearDown() + { + Mockery::close(); + } + + /** @test */ + public function it_should_return_the_user_if_found() + { + $this->builder->shouldReceive('first')->once()->withNoArgs()->andReturn((object) ['id' => 1]); + $this->model->shouldReceive('where')->once()->with('foo', 'bar')->andReturn($this->builder); + + $user = $this->user->getBy('foo', 'bar'); + + $this->assertEquals(1, $user->id); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Stubs/JWTProviderStub.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Stubs/JWTProviderStub.php new file mode 100644 index 0000000..f05ec18 --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Stubs/JWTProviderStub.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test\Stubs; + +use Tymon\JWTAuth\Providers\JWT\JWTProvider; + +class JWTProviderStub extends JWTProvider +{ +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/TokenTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/TokenTest.php new file mode 100644 index 0000000..c105dff --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/TokenTest.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test\Providers\JWT; + +use Tymon\JWTAuth\Token; + +class TokenTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->token = new Token('foo.bar.baz'); + } + + /** @test */ + public function it_should_return_the_token_when_casting_to_a_string() + { + $this->assertEquals((string) $this->token, $this->token); + } + + /** @test */ + public function it_should_return_the_token_when_calling_get_method() + { + $this->assertInternalType('string', $this->token->get()); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Validators/PayloadValidatorTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Validators/PayloadValidatorTest.php new file mode 100644 index 0000000..a0cb7df --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Validators/PayloadValidatorTest.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test; + +use Carbon\Carbon; +use Tymon\JWTAuth\Validators\PayloadValidator; + +class PayloadValidatorTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + Carbon::setTestNow(Carbon::createFromTimeStampUTC(123)); + $this->validator = new PayloadValidator(); + } + + /** @test */ + public function it_should_return_true_when_providing_a_valid_payload() + { + $payload = [ + 'iss' => 'http://example.com', + 'iat' => 100, + 'nbf' => 100, + 'exp' => 100 + 3600, + 'sub' => 1, + 'jti' => 'foo', + ]; + + $this->assertTrue($this->validator->isValid($payload)); + } + + /** @test */ + public function it_should_throw_an_exception_when_providing_an_expired_payload() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenExpiredException'); + + $payload = [ + 'iss' => 'http://example.com', + 'iat' => 20, + 'nbf' => 20, + 'exp' => 120, + 'sub' => 1, + 'jti' => 'foo', + ]; + + $this->validator->check($payload); + } + + /** @test */ + public function it_should_throw_an_exception_when_providing_an_invalid_nbf_claim() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException'); + + $payload = [ + 'iss' => 'http://example.com', + 'iat' => 100, + 'nbf' => 150, + 'exp' => 150 + 3600, + 'sub' => 1, + 'jti' => 'foo', + ]; + + $this->validator->check($payload); + } + + /** @test */ + public function it_should_throw_an_exception_when_providing_an_invalid_iat_claim() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException'); + + $payload = [ + 'iss' => 'http://example.com', + 'iat' => 150, + 'nbf' => 100, + 'exp' => 150 + 3600, + 'sub' => 1, + 'jti' => 'foo', + ]; + + $this->validator->check($payload); + } + + /** @test */ + public function it_should_throw_an_exception_when_providing_an_invalid_payload() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException'); + + $payload = [ + 'iss' => 'http://example.com', + 'sub' => 1, + ]; + + $this->validator->check($payload); + } + + /** @test */ + public function it_should_throw_an_exception_when_providing_an_invalid_expiry() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException'); + + $payload = [ + 'iss' => 'http://example.com', + 'iat' => 100, + 'exp' => 'foo', + 'sub' => 1, + 'jti' => 'foo', + ]; + + $this->validator->check($payload); + } + + /** @test **/ + public function it_should_throw_an_exception_when_required_claims_are_missing() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException'); + + $payload = [ + 'iss' => 'http://example.com', + 'foo' => 'bar', + // these are inserted to check for regression to a previous bug + // where the check would only compare keys of autoindexed name arrays + // (There are enough to account for all of the required claims' indices) + 'autoindexed', + 'autoindexed', + 'autoindexed', + 'autoindexed', + 'autoindexed', + 'autoindexed', + 'autoindexed', + ]; + + $this->validator->check($payload); + } +} diff --git a/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Validators/TokenValidatorTest.php b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Validators/TokenValidatorTest.php new file mode 100644 index 0000000..eb18ebb --- /dev/null +++ b/plugins/vdomah/jwtauth/vendor/tymon/jwt-auth/tests/Validators/TokenValidatorTest.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tymon\JWTAuth\Test; + +use Tymon\JWTAuth\Validators\TokenValidator; + +class TokenValidatorTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->validator = new TokenValidator(); + } + + /** @test */ + public function it_should_return_true_when_providing_a_well_formed_token() + { + $this->assertTrue($this->validator->isValid('one.two.three')); + } + + /** @test */ + public function it_should_return_false_when_providing_a_malformed_token() + { + $this->assertFalse($this->validator->isValid('one.two.three.four.five')); + } + + /** @test */ + public function it_should_throw_an_axception_when_providing_a_malformed_token() + { + $this->setExpectedException('Tymon\JWTAuth\Exceptions\TokenInvalidException'); + + $this->validator->check('one.two.three.four.five'); + } +} diff --git a/plugins/vdomah/jwtauth/views/_btn_generate.htm b/plugins/vdomah/jwtauth/views/_btn_generate.htm new file mode 100644 index 0000000..00010c8 --- /dev/null +++ b/plugins/vdomah/jwtauth/views/_btn_generate.htm @@ -0,0 +1,21 @@ + + + \ No newline at end of file