Mail Parser: Completely remove Webklex IMAP and all dependcies

This commit is contained in:
johnnyq
2026-06-24 13:39:07 -04:00
parent 63ad3256ee
commit 171a0d38f8
779 changed files with 6408 additions and 82971 deletions

View File

@@ -1,932 +0,0 @@
<?php
/*
* CRON - Email Parser (Webklex PHP-IMAP)
* Process emails and create/update tickets using Webklex\PHPIMAP instead of native IMAP
*/
// Start the timer
$script_start_time = microtime(true);
// Set working directory to the directory this cron script lives at.
chdir(dirname(__FILE__));
// Ensure we're running from command line
if (php_sapi_name() !== 'cli') {
die("This script must be run from the command line.\n");
}
// Autoload (Webklex & any composer deps)
require_once "../plugins/vendor/autoload.php";
// Get ITFlow config & helper functions
require_once "../config.php";
// Set Timezone
require_once "../includes/inc_set_timezone.php";
require_once "../functions.php";
// Get settings for the "default" company
require_once "../includes/load_global_settings.php";
$config_ticket_prefix = sanitizeInput($config_ticket_prefix);
$config_ticket_from_name = sanitizeInput($config_ticket_from_name);
$config_ticket_email_parse_unknown_senders = intval($row['config_ticket_email_parse_unknown_senders']);
// Get company name & phone & timezone
$sql = mysqli_query($mysqli, "SELECT * FROM companies, settings WHERE companies.company_id = settings.company_id AND companies.company_id = 1");
$row = mysqli_fetch_assoc($sql);
$company_name = sanitizeInput($row['company_name']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
// Check setting enabled
if ($config_ticket_email_parse == 0) {
logApp("Cron-Email-Parser", "error", "Cron Email Parser unable to run - not enabled in admin settings.");
exit("Email Parser: Feature is not enabled - check Settings > Ticketing > Email-to-ticket parsing. See https://docs.itflow.org/ticket_email_parse -- Quitting..");
}
// System temp directory & lock
$temp_dir = sys_get_temp_dir();
$lock_file_path = "{$temp_dir}/itflow_email_parser_{$installation_id}.lock";
if (file_exists($lock_file_path)) {
$file_age = time() - filemtime($lock_file_path);
if ($file_age > 300) {
unlink($lock_file_path);
logApp("Cron-Email-Parser", "warning", "Cron Email Parser detected a lock file was present but was over 5 minutes old so it removed it.");
} else {
logApp("Cron-Email-Parser", "warning", "Lock file present. Cron Email Parser attempted to execute but was already executing, so instead it terminated.");
exit("Script is already running. Exiting.");
}
}
file_put_contents($lock_file_path, "Locked");
// Ensure lock gets removed even on fatal error
register_shutdown_function(function() use ($lock_file_path) {
if (file_exists($lock_file_path)) {
@unlink($lock_file_path);
}
});
// Allowed attachment extensions
$allowed_extensions = array('jpg', 'jpeg', 'gif', 'png', 'webp', 'svg', 'pdf', 'txt', 'md', 'doc', 'docx', 'csv', 'xls', 'xlsx', 'xlsm', 'zip', 'tar', 'gz');
/** ------------------------------------------------------------------
* Ticket / Reply helpers (unchanged)
* ------------------------------------------------------------------ */
function addTicket($contact_id, $contact_name, $contact_email, $client_id, $date, $subject, $message, $attachments, $original_message_file, $ccs) {
global $mysqli, $config_app_name, $company_name, $company_phone, $config_ticket_prefix, $config_ticket_client_general_notifications, $config_ticket_new_ticket_notification_email, $config_base_url, $config_ticket_from_name, $config_ticket_from_email, $config_ticket_default_billable, $allowed_extensions;
$bad_pattern = "/do[\W_]*not[\W_]*reply|no[\W_]*reply/i"; // Email addresses to ignore
// Atomically increment and get the new ticket number
mysqli_query($mysqli, "
UPDATE settings
SET
config_ticket_next_number = LAST_INSERT_ID(config_ticket_next_number),
config_ticket_next_number = config_ticket_next_number + 1
WHERE company_id = 1
");
$ticket_number = mysqli_insert_id($mysqli);
// Clean up the message
$message = trim($message);
// Remove DOCTYPE and meta tags
$message = preg_replace('/<!DOCTYPE[^>]*>/i', '', $message);
$message = preg_replace('/<meta[^>]*>/i', '', $message);
// Remove <html>, <head>, <body> and their closing tags
$message = preg_replace('/<\/?(html|head|body)[^>]*>/i', '', $message);
// Collapse excess whitespace
$message = preg_replace('/\s+/', ' ', $message);
// Convert newlines to <br>
$message = nl2br($message);
// Wrap final formatted message
$message = "<i>Email from: <b>$contact_name</b> &lt;$contact_email&gt; at $date:-</i> <br><br><div style='line-height:1.5;'>$message</div>";
$ticket_prefix_esc = mysqli_real_escape_string($mysqli, $config_ticket_prefix);
$message_esc = mysqli_real_escape_string($mysqli, $message);
$contact_email_esc = mysqli_real_escape_string($mysqli, $contact_email);
$client_id = intval($client_id);
$url_key = randomString(32);
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$ticket_prefix_esc', ticket_number = $ticket_number, ticket_source = 'Email', ticket_subject = '$subject', ticket_details = '$message_esc', ticket_priority = 'Low', ticket_status = 1, ticket_billable = $config_ticket_default_billable, ticket_created_by = 0, ticket_contact_id = $contact_id, ticket_url_key = '$url_key', ticket_client_id = $client_id");
$id = mysqli_insert_id($mysqli);
// Logging
logAction("Ticket", "Create", "Email parser: Client contact $contact_email_esc created ticket $ticket_prefix_esc$ticket_number ($subject) ($id)", $client_id, $id);
mkdirMissing('../uploads/tickets/');
$att_dir = "../uploads/tickets/" . $id . "/";
mkdirMissing($att_dir);
// Move original .eml into the ticket folder
rename("../uploads/tmp/{$original_message_file}", "{$att_dir}/{$original_message_file}");
$original_message_file_esc = mysqli_real_escape_string($mysqli, $original_message_file);
mysqli_query($mysqli, "INSERT INTO ticket_attachments SET ticket_attachment_name = 'Original-parsed-email.eml', ticket_attachment_reference_name = '$original_message_file_esc', ticket_attachment_ticket_id = $id");
// Save non-inline attachments
foreach ($attachments as $attachment) {
$att_name = $attachment['name'];
$att_extension = strtolower(pathinfo($att_name, PATHINFO_EXTENSION));
if (in_array($att_extension, $allowed_extensions)) {
$att_saved_filename = md5(uniqid(rand(), true)) . '.' . $att_extension;
$att_saved_path = $att_dir . $att_saved_filename;
file_put_contents($att_saved_path, $attachment['content']);
$ticket_attachment_name = sanitizeInput($att_name);
$ticket_attachment_reference_name = sanitizeInput($att_saved_filename);
$ticket_attachment_name_esc = mysqli_real_escape_string($mysqli, $ticket_attachment_name);
$ticket_attachment_reference_name_esc = mysqli_real_escape_string($mysqli, $ticket_attachment_reference_name);
mysqli_query($mysqli, "INSERT INTO ticket_attachments SET ticket_attachment_name = '$ticket_attachment_name_esc', ticket_attachment_reference_name = '$ticket_attachment_reference_name_esc', ticket_attachment_ticket_id = $id");
} else {
$ticket_attachment_name_esc = mysqli_real_escape_string($mysqli, $att_name);
logAction("Ticket", "Edit", "Email parser: Blocked attachment $ticket_attachment_name_esc from Client contact $contact_email_esc for ticket $ticket_prefix_esc$ticket_number", $client_id, $id);
}
}
// Add unknown guests as ticket watcher
if ($client_id == 0 && !preg_match($bad_pattern, $contact_email_esc)) {
mysqli_query($mysqli, "INSERT INTO ticket_watchers SET watcher_email = '$contact_email_esc', watcher_ticket_id = $id");
}
// Add CCs as ticket watchers
foreach ($ccs as $cc) {
if (filter_var($cc, FILTER_VALIDATE_EMAIL) && !preg_match($bad_pattern, $cc)) {
$cc_esc = mysqli_real_escape_string($mysqli, $cc);
mysqli_query($mysqli, "INSERT INTO ticket_watchers SET watcher_email = '$cc_esc', watcher_ticket_id = $id");
}
}
// External email
$data = [];
if ($config_ticket_client_general_notifications == 1 && !preg_match($bad_pattern, $contact_email)) {
$subject_email = "Ticket created - [$config_ticket_prefix$ticket_number] - $subject";
$body = "<i style='color: #808080'>##- Please type your reply above this line -##</i><br><br>Hello $contact_name,<br><br>Thank you for your email. A ticket regarding \"$subject\" has been automatically created for you.<br><br>Ticket: $config_ticket_prefix$ticket_number<br>Subject: $subject<br>Status: New<br>Portal: <a href='https://$config_base_url/guest/guest_view_ticket.php?ticket_id=$id&url_key=$url_key'>View ticket</a><br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$data[] = [
'from' => $config_ticket_from_email,
'from_name' => $config_ticket_from_name,
'recipient' => $contact_email,
'recipient_name' => $contact_name,
'subject' => $subject_email,
'body' => mysqli_real_escape_string($mysqli, $body)
];
}
// Internal email
if ($config_ticket_new_ticket_notification_email) {
if ($client_id == 0) {
$client_name = "Guest";
$client_uri = '';
} else {
$client_sql = mysqli_query($mysqli, "SELECT client_name FROM clients WHERE client_id = $client_id");
$client_row = mysqli_fetch_assoc($client_sql);
$client_name = sanitizeInput($client_row['client_name']);
$client_uri = "&client_id=$client_id";
}
$email_subject = "$config_app_name - New Ticket - $client_name: $subject";
$email_body = "Hello, <br><br>This is a notification that a new ticket has been raised in ITFlow. <br>Client: $client_name<br>Priority: Low (email parsed)<br>Link: https://$config_base_url/agent/ticket.php?ticket_id=$id$client_uri <br><br>--------------------------------<br><br><b>$subject</b><br>$message";
$data[] = [
'from' => $config_ticket_from_email,
'from_name' => $config_ticket_from_name,
'recipient' => $config_ticket_new_ticket_notification_email,
'recipient_name' => $config_ticket_from_name,
'subject' => $email_subject,
'body' => mysqli_real_escape_string($mysqli, $email_body)
];
}
addToMailQueue($data);
customAction('ticket_create', $id);
return true;
}
function addReply($from_email, $date, $subject, $ticket_number, $message, $attachments) {
global $mysqli, $config_app_name, $company_name, $company_phone, $config_ticket_prefix, $config_base_url, $config_ticket_from_name, $config_ticket_from_email, $allowed_extensions;
$ticket_reply_type = 'Client';
// $message contains the raw HTML body from IMAP
// 1) Remove the reply separator and everything below it (HTML-aware)
// This matches: <i ...>##- Please type your reply above this line -##</i> and EVERYTHING after it
$message = preg_replace(
'/<i[^>]*>##-\s*Please\s+type\s+your\s+reply\s+above\s+this\s+line\s*-##<\/i>.*$/is',
'',
$message
);
// 2) Clean up the remaining message
// Remove DOCTYPE and meta tags
$message = preg_replace('/<!DOCTYPE[^>]*>/i', '', $message);
$message = preg_replace('/<meta[^>]*>/i', '', $message);
// Remove <html>, <head>, <body> and their closing tags
$message = preg_replace('/<\/?(html|head|body)[^>]*>/i', '', $message);
// Trim leading/trailing whitespace
$message = trim($message);
// Normalize line breaks to spaces
$message = preg_replace('/\r\n|\r|\n/', ' ', $message);
// Convert to <br> for HTML display
$message = nl2br($message);
// 3) Final wrapper
$message = "<i>Email from: $from_email at $date:-</i><br><br><div style='line-height:1.5;'>$message</div>";
$ticket_number_esc = intval($ticket_number);
$message_esc = mysqli_real_escape_string($mysqli, $message);
$from_email_esc = mysqli_real_escape_string($mysqli, $from_email);
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT ticket_id, ticket_subject, ticket_status, ticket_contact_id, ticket_client_id, contact_email, client_name
FROM tickets
LEFT JOIN contacts on tickets.ticket_contact_id = contacts.contact_id
LEFT JOIN clients on tickets.ticket_client_id = clients.client_id
WHERE ticket_number = $ticket_number_esc LIMIT 1"));
if ($row) {
$ticket_id = intval($row['ticket_id']);
$ticket_subject = sanitizeInput($row['ticket_subject']);
$ticket_status = sanitizeInput($row['ticket_status']);
$ticket_reply_contact = intval($row['ticket_contact_id']);
$ticket_contact_email = sanitizeInput($row['contact_email']);
$client_id = intval($row['ticket_client_id']);
if ($client_id) {
$client_uri = "&client_id=$client_id";
} else {
$client_uri = '';
}
$client_name = sanitizeInput($row['client_name']);
if ($ticket_status == 5) {
$config_ticket_prefix_esc = mysqli_real_escape_string($mysqli, $config_ticket_prefix);
$ticket_number_esc2 = mysqli_real_escape_string($mysqli, $ticket_number);
appNotify("Ticket", "Email parser: $from_email attempted to re-open ticket $config_ticket_prefix_esc$ticket_number_esc2 (ID $ticket_id) - check inbox manually to see email", "/agent/ticket.php?ticket_id=$ticket_id$client_uri", $client_id);
$email_subject = "Action required: This ticket is already closed";
$email_body = "Hi there, <br><br>You've tried to reply to a ticket that is closed - we won't see your response. <br><br>Please raise a new ticket by sending a new e-mail to our support address below. <br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$data = [
[
'from' => $config_ticket_from_email,
'from_name' => $config_ticket_from_name,
'recipient' => $from_email,
'recipient_name' => $from_email,
'subject' => $email_subject,
'body' => mysqli_real_escape_string($mysqli, $email_body)
]
];
addToMailQueue($data);
return true;
}
if (empty($ticket_contact_email) || $ticket_contact_email !== $from_email) {
$from_email_esc2 = mysqli_real_escape_string($mysqli, $from_email);
$row2 = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT contact_id FROM contacts WHERE contact_email = '$from_email_esc2' AND contact_client_id = $client_id LIMIT 1"));
if ($row2) {
$ticket_reply_contact = intval($row2['contact_id']);
} else {
$ticket_reply_type = 'Internal';
$ticket_reply_contact = '0';
$message = "<b>WARNING: Contact email mismatch</b><br>$message";
$message_esc = mysqli_real_escape_string($mysqli, $message);
}
}
mysqli_query($mysqli, "INSERT INTO ticket_replies SET ticket_reply = '$message_esc', ticket_reply_type = '$ticket_reply_type', ticket_reply_time_worked = '00:00:00', ticket_reply_by = $ticket_reply_contact, ticket_reply_ticket_id = $ticket_id");
$reply_id = mysqli_insert_id($mysqli);
$ticket_dir = "../uploads/tickets/" . $ticket_id . "/";
mkdirMissing($ticket_dir);
foreach ($attachments as $attachment) {
$att_name = $attachment['name'];
$att_extension = strtolower(pathinfo($att_name, PATHINFO_EXTENSION));
if (in_array($att_extension, $allowed_extensions)) {
$att_saved_filename = md5(uniqid(rand(), true)) . '.' . $att_extension;
$att_saved_path = $ticket_dir . $att_saved_filename;
file_put_contents($att_saved_path, $attachment['content']);
$ticket_attachment_name = sanitizeInput($att_name);
$ticket_attachment_reference_name = sanitizeInput($att_saved_filename);
$ticket_attachment_name_esc = mysqli_real_escape_string($mysqli, $ticket_attachment_name);
$ticket_attachment_reference_name_esc = mysqli_real_escape_string($mysqli, $ticket_attachment_reference_name);
mysqli_query($mysqli, "INSERT INTO ticket_attachments SET ticket_attachment_name = '$ticket_attachment_name_esc', ticket_attachment_reference_name = '$ticket_attachment_reference_name_esc', ticket_attachment_reply_id = $reply_id, ticket_attachment_ticket_id = $ticket_id");
} else {
$ticket_attachment_name_esc = mysqli_real_escape_string($mysqli, $att_name);
logAction("Ticket", "Edit", "Email parser: Blocked attachment $ticket_attachment_name_esc from Client contact $from_email_esc for ticket $config_ticket_prefix$ticket_number_esc", $client_id, $ticket_id);
}
}
$ticket_assigned_to_sql = mysqli_query($mysqli, "SELECT ticket_assigned_to FROM tickets WHERE ticket_id = $ticket_id LIMIT 1");
if ($ticket_assigned_to_sql) {
$row3 = mysqli_fetch_assoc($ticket_assigned_to_sql);
$ticket_assigned_to = intval($row3['ticket_assigned_to']);
if ($ticket_assigned_to) {
$tech_sql = mysqli_query($mysqli, "SELECT user_email, user_name FROM users WHERE user_id = $ticket_assigned_to LIMIT 1");
$tech_row = mysqli_fetch_assoc($tech_sql);
$tech_email = sanitizeInput($tech_row['user_email']);
$tech_name = sanitizeInput($tech_row['user_name']);
$email_subject = "$config_app_name - Ticket updated - [$config_ticket_prefix$ticket_number] $ticket_subject";
$email_body = "Hello $tech_name,<br><br>A new reply has been added to the below ticket.<br><br>Client: $client_name<br>Ticket: $config_ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Link: https://$config_base_url/agent/ticket.php?ticket_id=$ticket_id$client_uri<br><br>--------------------------------<br>$message_esc";
$data = [
[
'from' => $config_ticket_from_email,
'from_name' => $config_ticket_from_name,
'recipient' => $tech_email,
'recipient_name' => $tech_name,
'subject' => mysqli_real_escape_string($mysqli, $email_subject),
'body' => mysqli_real_escape_string($mysqli, $email_body)
]
];
addToMailQueue($data);
}
}
mysqli_query($mysqli, "UPDATE tickets SET ticket_status = 2, ticket_resolved_at = NULL WHERE ticket_id = $ticket_id AND ticket_client_id = $client_id LIMIT 1");
logAction("Ticket", "Edit", "Email parser: Client contact $from_email_esc updated ticket $config_ticket_prefix$ticket_number_esc ($subject)", $client_id, $ticket_id);
customAction('ticket_reply_client', $ticket_id);
return true;
} else {
return false;
}
}
/** ------------------------------------------------------------------
* OAuth helpers + provider guard
* ------------------------------------------------------------------ */
// returns true if expires_at ('Y-m-d H:i:s') is in the past (or missing)
function tokenExpired(?string $expires_at): bool {
if (empty($expires_at)) return true;
$ts = strtotime($expires_at);
if ($ts === false) return true;
// refresh a little early (60s) to avoid race
return ($ts - 60) <= time();
}
// very small form-encoded POST helper using curl
function httpFormPost(string $url, array $fields): array {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields, '', '&'));
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
$raw = curl_exec($ch);
$err = curl_error($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return ['ok' => ($raw !== false && $code >= 200 && $code < 300), 'body' => $raw, 'code' => $code, 'err' => $err];
}
/**
* Get a valid access token for Google Workspace IMAP via refresh token if needed.
* Uses settings: config_mail_oauth_client_id / _client_secret / _refresh_token / _access_token / _access_token_expires_at
* Updates globals if refreshed (so later logging can reflect it if you want to persist).
*/
function getGoogleAccessToken(string $username): ?string {
// pull from global settings variables you already load
global $mysqli,
$config_mail_oauth_client_id,
$config_mail_oauth_client_secret,
$config_mail_oauth_refresh_token,
$config_mail_oauth_access_token,
$config_mail_oauth_access_token_expires_at;
// If we have a not-expired token, use it
if (!empty($config_mail_oauth_access_token) && !tokenExpired($config_mail_oauth_access_token_expires_at)) {
return $config_mail_oauth_access_token;
}
// Need to refresh?
if (empty($config_mail_oauth_client_id) || empty($config_mail_oauth_client_secret) || empty($config_mail_oauth_refresh_token)) {
// Nothing we can do
return null;
}
$resp = httpFormPost(
'https://oauth2.googleapis.com/token',
[
'client_id' => $config_mail_oauth_client_id,
'client_secret' => $config_mail_oauth_client_secret,
'refresh_token' => $config_mail_oauth_refresh_token,
'grant_type' => 'refresh_token',
]
);
if (!$resp['ok']) return null;
$json = json_decode($resp['body'], true);
if (!is_array($json) || empty($json['access_token'])) return null;
// Calculate new expiry
$expires_at = date('Y-m-d H:i:s', time() + (int)($json['expires_in'] ?? 3600));
// Update in-memory globals (and persist to DB)
$config_mail_oauth_access_token = $json['access_token'];
$config_mail_oauth_access_token_expires_at = $expires_at;
$at_esc = mysqli_real_escape_string($mysqli, $config_mail_oauth_access_token);
$exp_esc = mysqli_real_escape_string($mysqli, $config_mail_oauth_access_token_expires_at);
mysqli_query($mysqli, "UPDATE settings SET
config_mail_oauth_access_token = '{$at_esc}',
config_mail_oauth_access_token_expires_at = '{$exp_esc}'
WHERE company_id = 1
");
return $config_mail_oauth_access_token;
}
/**
* Get a valid access token for Microsoft 365 IMAP via refresh token if needed.
* Uses settings: config_mail_oauth_client_id / _client_secret / _tenant_id / _refresh_token / _access_token / _access_token_expires_at
*/
function getMicrosoftAccessToken(string $username): ?string {
global $mysqli,
$config_mail_oauth_client_id,
$config_mail_oauth_client_secret,
$config_mail_oauth_tenant_id,
$config_mail_oauth_refresh_token,
$config_mail_oauth_access_token,
$config_mail_oauth_access_token_expires_at;
if (!empty($config_mail_oauth_access_token) && !tokenExpired($config_mail_oauth_access_token_expires_at)) {
return $config_mail_oauth_access_token;
}
if (empty($config_mail_oauth_client_id) || empty($config_mail_oauth_client_secret) || empty($config_mail_oauth_refresh_token) || empty($config_mail_oauth_tenant_id)) {
return null;
}
$url = "https://login.microsoftonline.com/".rawurlencode($config_mail_oauth_tenant_id)."/oauth2/v2.0/token";
$resp = httpFormPost($url, [
'client_id' => $config_mail_oauth_client_id,
'client_secret' => $config_mail_oauth_client_secret,
'refresh_token' => $config_mail_oauth_refresh_token,
'grant_type' => 'refresh_token',
// IMAP/SMTP scopes typically included at initial consent; not needed for refresh
]);
if (!$resp['ok']) return null;
$json = json_decode($resp['body'], true);
if (!is_array($json) || empty($json['access_token'])) return null;
$expires_at = date('Y-m-d H:i:s', time() + (int)($json['expires_in'] ?? 3600));
$config_mail_oauth_access_token = $json['access_token'];
$config_mail_oauth_access_token_expires_at = $expires_at;
$at_esc = mysqli_real_escape_string($mysqli, $config_mail_oauth_access_token);
$exp_esc = mysqli_real_escape_string($mysqli, $config_mail_oauth_access_token_expires_at);
mysqli_query($mysqli, "UPDATE settings SET
config_mail_oauth_access_token = '{$at_esc}',
config_mail_oauth_access_token_expires_at = '{$exp_esc}'
WHERE company_id = 1
");
return $config_mail_oauth_access_token;
}
// Provider from settings (may be NULL/empty to disable IMAP polling)
$imap_provider = $config_imap_provider ?? '';
if ($imap_provider === null) $imap_provider = '';
if ($imap_provider === '') {
// IMAP disabled by admin: exit cleanly
logApp("Cron-Email-Parser", "info", "IMAP polling skipped: provider not configured.");
@unlink($lock_file_path);
exit(0);
}
/** ------------------------------------------------------------------
* Webklex IMAP setup (supports Standard / Google OAuth / Microsoft OAuth)
* ------------------------------------------------------------------ */
use Webklex\PHPIMAP\ClientManager;
$validate_cert = true;
// Defaults from settings (standard IMAP)
$host = $config_imap_host;
$port = (int)$config_imap_port;
$encr = !empty($config_imap_encryption) ? $config_imap_encryption : 'notls'; // 'ssl'|'tls'|'notls'
$user = $config_imap_username;
$pass = $config_imap_password;
$auth = null; // 'oauth' for OAuth providers
if ($imap_provider === 'google_oauth') {
$host = 'imap.gmail.com';
$port = 993;
$encr = 'ssl';
$auth = 'oauth';
$pass = getGoogleAccessToken($user);
if (empty($pass)) {
logApp("Cron-Email-Parser", "error", "Google OAuth: no usable access token (check refresh token/client credentials).");
@unlink($lock_file_path);
exit(1);
}
} elseif ($imap_provider === 'microsoft_oauth') {
$host = 'outlook.office365.com';
$port = 993;
$encr = 'ssl';
$auth = 'oauth';
$pass = getMicrosoftAccessToken($user);
if (empty($pass)) {
logApp("Cron-Email-Parser", "error", "Microsoft OAuth: no usable access token (check refresh token/client credentials/tenant).");
@unlink($lock_file_path);
exit(1);
}
} else {
// standard_imap (username/password)
if (empty($host) || empty($port) || empty($user)) {
logApp("Cron-Email-Parser", "error", "Standard IMAP: missing host/port/username.");
@unlink($lock_file_path);
exit(1);
}
}
$cm = new ClientManager();
$client = $cm->make(array_filter([
'host' => $host,
'port' => $port,
'encryption' => $encr, // 'ssl' | 'tls' | null
'validate_cert' => (bool)$validate_cert,
'username' => $user, // full mailbox address (OAuth uses user as principal)
'password' => $pass, // access token when $auth === 'oauth'
'authentication' => $auth, // 'oauth' or null
'protocol' => 'imap',
]));
try {
$client->connect();
} catch (\Throwable $e) {
echo "Error connecting to IMAP server: " . $e->getMessage();
@unlink($lock_file_path);
exit(1);
}
$inbox = $client->getFolderByPath('INBOX');
$targetFolderPath = 'ITFlow';
try {
$targetFolder = $client->getFolderByPath($targetFolderPath);
} catch (\Throwable $e) {
$client->createFolder($targetFolderPath);
$targetFolder = $client->getFolderByPath($targetFolderPath);
}
// Fetch unseen messages
$messages = $inbox->messages()->leaveUnread()->unseen()->get();
// Counters
$processed_count = 0;
$unprocessed_count = 0;
// Process messages
foreach ($messages as $message) {
$email_processed = false;
// Save original message as .eml (getRawMessage() doesn't seem to work properly)
mkdirMissing('../uploads/tmp/');
$original_message_file = "processed-eml-" . randomString(200) . ".eml";
$raw_message = (string)$message->getHeader()->raw . "\r\n\r\n" . ($message->getRawBody() ?? $message->getHTMLBody() ?? $message->getTextBody());
file_put_contents("../uploads/tmp/{$original_message_file}", $raw_message);
// From
$from_col = $message->getFrom();
$from_first = ($from_col && $from_col->count()) ? $from_col->first() : null;
$from_email = sanitizeInput($from_first->mail ?? 'itflow-guest@example.com');
$from_name = sanitizeInput($from_first->personal ?? 'Unknown');
$from_domain = explode("@", $from_email);
$from_domain = sanitizeInput(end($from_domain));
// Subject
$subject = sanitizeInput((string)$message->getSubject() ?: 'No Subject');
// CC
$ccs = array();
$cc_attr = $message->header->cc;
$cc_list = $cc_attr->toArray();
foreach ($cc_list as $cc_addr) {
if ($cc_addr instanceof \Webklex\PHPIMAP\Address) {
$ccs[] = $cc_addr->mail;
}
}
// Date (string)
$dateAttr = $message->getDate(); // Attribute
$dateRaw = $dateAttr ? (string)$dateAttr : ''; // e.g. "Tue, 10 Sep 2025 13:22:05 +0000"
$ts = $dateRaw ? strtotime($dateRaw) : false;
$date = sanitizeInput($ts !== false ? date('Y-m-d H:i:s', $ts) : date('Y-m-d H:i:s'));
// Body (prefer HTML)
$message_body_html = $message->getHTMLBody();
$message_body_text = $message->getTextBody();
$message_body_raw = $message->getRawBody();
if (!empty($message_body_html)) {
$message_body = $message_body_html;
} elseif (!empty($message_body_text)) {
$message_body = nl2br(htmlspecialchars($message_body_text));
} else {
// Final fallback
$message_body = nl2br(htmlspecialchars($message_body_raw));
}
// Handle attachments (inline vs regular)
$attachments = [];
foreach ($message->getAttachments() as $att) {
$attrs = $att->getAttributes(); // v6.2: canonical source
$dispo = strtolower((string)($attrs['disposition'] ?? ''));
$cid = $attrs['id'] ?? null; // Content-ID
$content = $attrs['content'] ?? null; // binary
$mime = $att->getMimeType();
$name = $att->getName() ?: 'attachment';
$is_inline = false;
if ($dispo === 'inline' && $cid && $content !== null) {
$cid_trim = trim($cid, '<>');
$dataUri = "data:$mime;base64,".base64_encode($content);
$message_body = str_replace(["cid:$cid_trim", "cid:$cid"], $dataUri, $message_body);
$is_inline = true;
}
if (!$is_inline && $content !== null) {
$attachments[] = ['name' => $name, 'content' => $content];
}
}
// 1. Reply to existing ticket with the number in subject
if (preg_match("/\[$config_ticket_prefix(\d+)\]/", $subject, $ticket_number_matches)) {
$ticket_number = intval($ticket_number_matches[1]);
$email_processed = addReply($from_email, $date, $subject, $ticket_number, $message_body, $attachments);
}
// 2. Fuzzy duplicate check using a known contact/domain and similar_text subject
if (!$email_processed && strlen(trim($subject)) > 10) {
$contact_id = 0;
$client_id = 0;
// First: check if sender is a registered contact
$from_email_esc = mysqli_real_escape_string($mysqli, $from_email);
$contact_sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_email = '$from_email_esc' AND contact_archived_at IS NULL LIMIT 1");
$contact_row = mysqli_fetch_assoc($contact_sql);
if ($contact_row) {
$contact_id = intval($contact_row['contact_id']);
$client_id = intval($contact_row['contact_client_id']);
} else {
// Else: check if sender domain is registered
$from_domain_esc = mysqli_real_escape_string($mysqli, $from_domain);
$domain_sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_name = '$from_domain_esc' AND domain_archived_at IS NULL LIMIT 1");
$domain_row = mysqli_fetch_assoc($domain_sql);
if ($domain_row && $from_domain == $domain_row['domain_name']) {
$client_id = intval($domain_row['domain_client_id']);
}
}
// If we found either a contact or a domain, check recent tickets for a matching subject
if ($client_id) {
$recent_tickets_sql = mysqli_query($mysqli,
"SELECT ticket_id, ticket_number, ticket_subject
FROM tickets
WHERE ticket_client_id = $client_id AND ticket_resolved_at IS NULL
AND ticket_created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)"
);
while ($rowt = mysqli_fetch_assoc($recent_tickets_sql)) {
$ticket_number = intval($rowt['ticket_number']);
$existing_subject = $rowt['ticket_subject'];
// Calculate similarity percentage
similar_text(strtolower($subject), strtolower($existing_subject), $percent);
if ($percent >= 95) {
// Treat as a reply/duplicate
$email_processed = addReply($from_email, $date, $subject, $ticket_number, $message_body, $attachments);
break;
}
}
}
}
// 3. A known, registered contact?
if (!$email_processed) {
$from_email_esc = mysqli_real_escape_string($mysqli, $from_email);
$any_contact_sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_email = '$from_email_esc' AND contact_archived_at IS NULL LIMIT 1");
$rowc = mysqli_fetch_assoc($any_contact_sql);
if ($rowc) {
$contact_name = sanitizeInput($rowc['contact_name']);
$contact_id = intval($rowc['contact_id']);
$contact_email = sanitizeInput($rowc['contact_email']);
$client_id = intval($rowc['contact_client_id']);
$email_processed = addTicket($contact_id, $contact_name, $contact_email, $client_id, $date, $subject, $message_body, $attachments, $original_message_file, $ccs);
}
}
// 4. A known domain?
if (!$email_processed) {
$from_domain_esc = mysqli_real_escape_string($mysqli, $from_domain);
$domain_sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_name = '$from_domain_esc' AND domain_archived_at IS NULL LIMIT 1");
$rowd = mysqli_fetch_assoc($domain_sql);
if ($rowd && $from_domain == $rowd['domain_name']) {
$client_id = intval($rowd['domain_client_id']);
// Create a new contact
$contact_name = $from_name;
$contact_email = $from_email;
mysqli_query($mysqli, "INSERT INTO contacts SET contact_name = '".mysqli_real_escape_string($mysqli, $contact_name)."', contact_email = '".mysqli_real_escape_string($mysqli, $contact_email)."', contact_notes = 'Added automatically via email parsing.', contact_client_id = $client_id");
$contact_id = mysqli_insert_id($mysqli);
logAction("Contact", "Create", "Email parser: created contact " . mysqli_real_escape_string($mysqli, $contact_name), $client_id, $contact_id);
customAction('contact_create', $contact_id);
$email_processed = addTicket($contact_id, $contact_name, $contact_email, $client_id, $date, $subject, $message_body, $attachments, $original_message_file, $ccs);
}
}
// 5. Unknown sender allowed?
if (!$email_processed && $config_ticket_email_parse_unknown_senders) {
$bad_from_pattern = "/daemon|postmaster|bounce|mta/i"; // Stop NDRs with bad subjects raising new tickets
if (!preg_match($bad_from_pattern, $from_email)) {
$email_processed = addTicket(0, $from_name, $from_email, 0, $date, $subject, $message_body, $attachments, $original_message_file, $ccs);
} else {
// Probably an NDR message without a ticket ref in the subject
$failed_recipient = null;
$diagnostic_code = null;
$status_code = null;
$original_subject = null;
$original_to = null;
// Webklex stores DSN info in attachments, not parts
foreach ($message->getAttachments() as $attachment) {
$ctype = strtolower($attachment->getContentType());
$body = $attachment->getContent() ?? '';
// 1. Delivery status block
if (strpos($ctype, 'delivery-status') !== false) {
if (preg_match('/Final-Recipient:\s*rfc822;\s*(.+)/i', $body, $m)) {
$failed_recipient = sanitizeInput(trim($m[1]));
}
if (preg_match('/Diagnostic-Code:\s*(.+)/i', $body, $m)) {
$diagnostic_code = sanitizeInput(trim($m[1]));
}
if (preg_match('/Status:\s*([0-9\.]+)/i', $body, $m)) {
$status_code = sanitizeInput(trim($m[1]));
}
}
// 2. Original message headers
if (strpos($ctype, 'message/rfc822') !== false) {
if (preg_match('/^To:\s*(.+)$/mi', $body, $m)) {
$original_to = sanitizeInput(trim($m[1]));
}
if (preg_match('/^Subject:\s*(.+)$/mi', $body, $m)) {
$original_subject = sanitizeInput(trim($m[1]));
}
}
}
// 3. Fallback: extract diagnostic from human-readable text/plain
if (!$diagnostic_code) {
$text = $message->getTextBody() ?? '';
// Exim puts diagnostics on an indented line
if (preg_match('/\n\s{2,}(.+)/', $text, $m)) {
$diagnostic_code = sanitizeInput(trim($m[1]));
}
}
// Fallbacks
$failed_recipient = $failed_recipient ?: 'unknown recipient';
$diagnostic_code = $diagnostic_code ?: 'unknown diagnostic code';
$status_code = $status_code ?: 'unknown status code';
$original_subject = $original_subject ?: $subject;
appNotify(
"Ticket",
"Email parser NDR: Message to $failed_recipient bounced. Subject: $original_subject Diagnostics: $status_code / $diagnostic_code - check ITFlow folder manually to see email",
"",
0
);
// If the original subject has a ticket, add the NDR there too
if (preg_match("/\[$config_ticket_prefix(\d+)\]/", $original_subject, $ticket_number_matches)) {
$ticket_number = intval($ticket_number_matches[1]);
// Craft a clean bounce message
$reply_body = "Email delivery failed.\n".
"Recipient: $failed_recipient\n".
"Status: $status_code\n".
"Diagnostic: $diagnostic_code\n";
// No attachments
addReply(
$from_email,
$date,
$original_subject,
$ticket_number,
$reply_body,
[]
);
}
$email_processed = true;
}
}
// Flag/move based on processing result
if ($email_processed) {
$processed_count++; // increment first so a move failure doesn't hide the success
try {
$message->setFlag('Seen');
// Move using the Folder object (top-level "ITFlow")
$message->move($targetFolderPath);
// optional: logApp("Cron-Email-Parser", "info", "Moved message to ITFlow");
} catch (\Throwable $e) {
// >>> Put the extra logging RIGHT HERE
$subj = (string)$message->getSubject();
$uid = method_exists($message, 'getUid') ? $message->getUid() : 'n/a';
$path = (is_object($targetFolder) && property_exists($targetFolder, 'path')) ? (string)$targetFolder->path : $targetFolderPath;
logApp(
"Cron-Email-Parser",
"warning",
"Move failed (subject=\"$subj\", uid=$uid) to [$path]: ".$e->getMessage()
);
}
} else {
$unprocessed_count++;
try {
$message->setFlag('Flagged');
$message->unsetFlag('Seen');
} catch (\Throwable $e) {
logApp("Cron-Email-Parser", "warning", "Flag update failed: ".$e->getMessage());
}
}
// Cleanup temp .eml if still present (e.g., reply path)
if (isset($original_message_file)) {
$tmp_path = "../uploads/tmp/{$original_message_file}";
if (file_exists($tmp_path)) { @unlink($tmp_path); }
}
}
// Expunge & disconnect
try {
$client->expunge();
} catch (\Throwable $e) {
// ignore
}
$client->disconnect();
// Execution timing (optional)
$script_end_time = microtime(true);
$execution_time = $script_end_time - $script_start_time;
$execution_time_formatted = number_format($execution_time, 2);
$processed_info = "Processed: $processed_count email(s), Unprocessed: $unprocessed_count email(s)";
// logAction("Cron-Email-Parser", "Execution", "Cron Email Parser executed in $execution_time_formatted seconds. $processed_info");
// Remove the lock file
unlink($lock_file_path);
// DEBUG
echo "\nLock File Path: $lock_file_path\n";
if (file_exists($lock_file_path)) {
echo "\nLock is present\n\n";
}
echo "Processed Emails: $processed_count\n";
echo "Unprocessed Emails: $unprocessed_count\n";

View File

@@ -1,6 +1,5 @@
{
"require": {
"webklex/php-imap": "^6.2",
"directorytree/imapengine": "^1.24"
},
"config": {

556
plugins/composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ab8e2fdad19a8ca7b697fc24a24b9194",
"content-hash": "2c0fb0fc225c899ec2e8e5f612429def",
"packages": [
{
"name": "carbonphp/carbon-doctrine-types",
@@ -77,16 +77,16 @@
},
{
"name": "directorytree/imapengine",
"version": "v1.24.1",
"version": "v1.25.0",
"source": {
"type": "git",
"url": "https://github.com/DirectoryTree/ImapEngine.git",
"reference": "d545ff3f6d2155ce7f9f612f0444579477d7bab8"
"reference": "ac8a4d028334c2d3a4bc8fd975317a75cd968a47"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/DirectoryTree/ImapEngine/zipball/d545ff3f6d2155ce7f9f612f0444579477d7bab8",
"reference": "d545ff3f6d2155ce7f9f612f0444579477d7bab8",
"url": "https://api.github.com/repos/DirectoryTree/ImapEngine/zipball/ac8a4d028334c2d3a4bc8fd975317a75cd968a47",
"reference": "ac8a4d028334c2d3a4bc8fd975317a75cd968a47",
"shasum": ""
},
"require": {
@@ -127,7 +127,7 @@
],
"support": {
"issues": "https://github.com/DirectoryTree/ImapEngine/issues",
"source": "https://github.com/DirectoryTree/ImapEngine/tree/v1.24.1"
"source": "https://github.com/DirectoryTree/ImapEngine/tree/v1.25.0"
},
"funding": [
{
@@ -135,97 +135,7 @@
"type": "github"
}
],
"time": "2026-05-20T13:36:53+00:00"
},
{
"name": "doctrine/inflector",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b",
"reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^12.0 || ^13.0",
"phpstan/phpstan": "^1.12 || ^2.0",
"phpstan/phpstan-phpunit": "^1.4 || ^2.0",
"phpstan/phpstan-strict-rules": "^1.6 || ^2.0",
"phpunit/phpunit": "^8.5 || ^12.2"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Inflector\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
"keywords": [
"inflection",
"inflector",
"lowercase",
"manipulation",
"php",
"plural",
"singular",
"strings",
"uppercase",
"words"
],
"support": {
"issues": "https://github.com/doctrine/inflector/issues",
"source": "https://github.com/doctrine/inflector/tree/2.1.0"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
"type": "tidelift"
}
],
"time": "2025-08-10T19:31:58+00:00"
"time": "2026-06-19T17:03:06+00:00"
},
{
"name": "doctrine/lexer",
@@ -373,16 +283,16 @@
},
{
"name": "guzzlehttp/psr7",
"version": "2.11.0",
"version": "2.12.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "bbb5e61349fa5cb822b3e87842b951088b76b81f"
"reference": "7ec62dc3f44aa218487dbed81a9bf9bc647be55d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/bbb5e61349fa5cb822b3e87842b951088b76b81f",
"reference": "bbb5e61349fa5cb822b3e87842b951088b76b81f",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/7ec62dc3f44aa218487dbed81a9bf9bc647be55d",
"reference": "7ec62dc3f44aa218487dbed81a9bf9bc647be55d",
"shasum": ""
},
"require": {
@@ -391,7 +301,7 @@
"psr/http-message": "^1.1 || ^2.0",
"ralouphie/getallheaders": "^3.0",
"symfony/deprecation-contracts": "^2.5 || ^3.0",
"symfony/polyfill-php80": "^1.24"
"symfony/polyfill-php80": "^1.25"
},
"provide": {
"psr/http-factory-implementation": "1.0",
@@ -472,7 +382,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.11.0"
"source": "https://github.com/guzzle/psr7/tree/2.12.3"
},
"funding": [
{
@@ -488,7 +398,7 @@
"type": "tidelift"
}
],
"time": "2026-06-02T12:30:48+00:00"
"time": "2026-06-23T15:21:08+00:00"
},
{
"name": "illuminate/collections",
@@ -690,187 +600,6 @@
},
"time": "2026-03-30T19:05:19+00:00"
},
{
"name": "illuminate/pagination",
"version": "v12.62.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/pagination.git",
"reference": "8327d828676654053906a771abf5eea5426354ec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/pagination/zipball/8327d828676654053906a771abf5eea5426354ec",
"reference": "8327d828676654053906a771abf5eea5426354ec",
"shasum": ""
},
"require": {
"ext-filter": "*",
"illuminate/collections": "^12.0",
"illuminate/contracts": "^12.0",
"illuminate/support": "^12.0",
"php": "^8.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "12.x-dev"
}
},
"autoload": {
"psr-4": {
"Illuminate\\Pagination\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Pagination package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2026-02-25T15:25:18+00:00"
},
{
"name": "illuminate/reflection",
"version": "v12.62.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/reflection.git",
"reference": "348cf5da9de89b596d7723be6425fb048e2bf4bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/reflection/zipball/348cf5da9de89b596d7723be6425fb048e2bf4bb",
"reference": "348cf5da9de89b596d7723be6425fb048e2bf4bb",
"shasum": ""
},
"require": {
"illuminate/collections": "^12.0",
"illuminate/contracts": "^12.0",
"php": "^8.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "12.x-dev"
}
},
"autoload": {
"files": [
"helpers.php"
],
"psr-4": {
"Illuminate\\Support\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Reflection package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2026-02-25T15:25:18+00:00"
},
{
"name": "illuminate/support",
"version": "v12.62.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
"reference": "3a8772095ef7d6b1961a77f2f0b8921c056c48ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/support/zipball/3a8772095ef7d6b1961a77f2f0b8921c056c48ea",
"reference": "3a8772095ef7d6b1961a77f2f0b8921c056c48ea",
"shasum": ""
},
"require": {
"doctrine/inflector": "^2.0",
"ext-ctype": "*",
"ext-filter": "*",
"ext-mbstring": "*",
"illuminate/collections": "^12.0",
"illuminate/conditionable": "^12.0",
"illuminate/contracts": "^12.0",
"illuminate/macroable": "^12.0",
"illuminate/reflection": "^12.0",
"nesbot/carbon": "^3.8.4",
"php": "^8.2",
"symfony/polyfill-php83": "^1.33",
"symfony/polyfill-php85": "^1.33",
"voku/portable-ascii": "^2.0.2"
},
"conflict": {
"tightenco/collect": "<5.5.33"
},
"replace": {
"spatie/once": "*"
},
"suggest": {
"illuminate/filesystem": "Required to use the Composer class (^12.0).",
"laravel/serializable-closure": "Required to use the once function (^1.3|^2.0).",
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.7).",
"league/uri": "Required to use the Uri class (^7.5.1).",
"ramsey/uuid": "Required to use Str::uuid() (^4.7).",
"symfony/process": "Required to use the Composer class (^7.2).",
"symfony/uid": "Required to use Str::ulid() (^7.2).",
"symfony/var-dumper": "Required to use the dd function (^7.2).",
"vlucas/phpdotenv": "Required to use the Env class and env helper (^5.6.1)."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "12.x-dev"
}
},
"autoload": {
"files": [
"functions.php",
"helpers.php"
],
"psr-4": {
"Illuminate\\Support\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Support package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2026-05-31T22:10:17+00:00"
},
{
"name": "laravel/serializable-closure",
"version": "v2.0.13",
@@ -934,16 +663,16 @@
},
{
"name": "nesbot/carbon",
"version": "3.11.4",
"version": "3.13.0",
"source": {
"type": "git",
"url": "https://github.com/CarbonPHP/carbon.git",
"reference": "e890471a3494740f7d9326d72ce6a8c559ffee60"
"reference": "40f6618f052df16b545f626fbf9a878e6497d16a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/e890471a3494740f7d9326d72ce6a8c559ffee60",
"reference": "e890471a3494740f7d9326d72ce6a8c559ffee60",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/40f6618f052df16b545f626fbf9a878e6497d16a",
"reference": "40f6618f052df16b545f626fbf9a878e6497d16a",
"shasum": ""
},
"require": {
@@ -1035,7 +764,7 @@
"type": "tidelift"
}
],
"time": "2026-04-07T09:57:54+00:00"
"time": "2026-06-18T13:49:15+00:00"
},
{
"name": "php-di/invoker",
@@ -1668,88 +1397,6 @@
],
"time": "2026-04-13T15:52:40+00:00"
},
{
"name": "symfony/http-foundation",
"version": "v7.4.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "bc354f47c62301e990b7874fa662326368508e2c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/bc354f47c62301e990b7874fa662326368508e2c",
"reference": "bc354f47c62301e990b7874fa662326368508e2c",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "^1.1"
},
"conflict": {
"doctrine/dbal": "<3.6",
"symfony/cache": "<6.4.12|>=7.0,<7.1.5"
},
"require-dev": {
"doctrine/dbal": "^3.6|^4",
"predis/predis": "^1.1|^2.0",
"symfony/cache": "^6.4.12|^7.1.5|^8.0",
"symfony/clock": "^6.4|^7.0|^8.0",
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
"symfony/expression-language": "^6.4|^7.0|^8.0",
"symfony/http-kernel": "^6.4|^7.0|^8.0",
"symfony/mime": "^6.4|^7.0|^8.0",
"symfony/rate-limiter": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\HttpFoundation\\": ""
},
"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": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-foundation/tree/v7.4.13"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2026-05-24T11:20:33+00:00"
},
{
"name": "symfony/mime",
"version": "v7.4.13",
@@ -2686,173 +2333,18 @@
],
"time": "2026-01-05T13:30:16+00:00"
},
{
"name": "voku/portable-ascii",
"version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/voku/portable-ascii.git",
"reference": "8e1051fe39379367aecf014f41744ce7539a856f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/voku/portable-ascii/zipball/8e1051fe39379367aecf014f41744ce7539a856f",
"reference": "8e1051fe39379367aecf014f41744ce7539a856f",
"shasum": ""
},
"require": {
"php": ">=7.1.0"
},
"require-dev": {
"phpunit/phpunit": "~8.5 || ~9.6 || ~10.5 || ~11.5"
},
"suggest": {
"ext-intl": "Use Intl for transliterator_transliterate() support"
},
"type": "library",
"autoload": {
"psr-4": {
"voku\\": "src/voku/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Lars Moelleken",
"homepage": "https://www.moelleken.org/"
}
],
"description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
"homepage": "https://github.com/voku/portable-ascii",
"keywords": [
"ascii",
"clean",
"php"
],
"support": {
"issues": "https://github.com/voku/portable-ascii/issues",
"source": "https://github.com/voku/portable-ascii/tree/2.1.1"
},
"funding": [
{
"url": "https://www.paypal.me/moelleken",
"type": "custom"
},
{
"url": "https://github.com/voku",
"type": "github"
},
{
"url": "https://opencollective.com/portable-ascii",
"type": "open_collective"
},
{
"url": "https://www.patreon.com/voku",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
"type": "tidelift"
}
],
"time": "2026-04-26T05:33:54+00:00"
},
{
"name": "webklex/php-imap",
"version": "6.2.0",
"source": {
"type": "git",
"url": "https://github.com/Webklex/php-imap.git",
"reference": "6b8ef85d621bbbaf52741b00cca8e9237e2b2e05"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Webklex/php-imap/zipball/6b8ef85d621bbbaf52741b00cca8e9237e2b2e05",
"reference": "6b8ef85d621bbbaf52741b00cca8e9237e2b2e05",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"ext-iconv": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-zip": "*",
"illuminate/pagination": ">=5.0.0",
"nesbot/carbon": "^2.62.1|^3.2.4",
"php": "^8.0.2",
"symfony/http-foundation": ">=2.8.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5.10"
},
"suggest": {
"symfony/mime": "Recomended for better extension support",
"symfony/var-dumper": "Usefull tool for debugging"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.0-dev"
}
},
"autoload": {
"psr-4": {
"Webklex\\PHPIMAP\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Malte Goldenbaum",
"email": "github@webklex.com",
"role": "Developer"
}
],
"description": "PHP IMAP client",
"homepage": "https://github.com/webklex/php-imap",
"keywords": [
"imap",
"mail",
"php-imap",
"pop3",
"webklex"
],
"support": {
"issues": "https://github.com/Webklex/php-imap/issues",
"source": "https://github.com/Webklex/php-imap/tree/6.2.0"
},
"funding": [
{
"url": "https://www.buymeacoffee.com/webklex",
"type": "custom"
},
{
"url": "https://ko-fi.com/webklex",
"type": "ko_fi"
}
],
"time": "2025-04-25T06:02:37+00:00"
},
{
"name": "zbateson/mail-mime-parser",
"version": "3.0.5",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/zbateson/mail-mime-parser.git",
"reference": "ff054c8e05310c445c2028c6128a4319cc9f6aa8"
"reference": "395c406cc1c5d1eb171d9decb0a3b509e8bd6bc0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/ff054c8e05310c445c2028c6128a4319cc9f6aa8",
"reference": "ff054c8e05310c445c2028c6128a4319cc9f6aa8",
"url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/395c406cc1c5d1eb171d9decb0a3b509e8bd6bc0",
"reference": "395c406cc1c5d1eb171d9decb0a3b509e8bd6bc0",
"shasum": ""
},
"require": {
@@ -2915,7 +2407,7 @@
"type": "github"
}
],
"time": "2025-12-02T00:29:16+00:00"
"time": "2026-06-24T13:42:46+00:00"
},
{
"name": "zbateson/mb-wrapper",

View File

@@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit9b9826e5b5cc7806cd328c4112cca75e::getLoader();
return ComposerAutoloaderInitc3c4b7d024f8d7c21b5ca31de3cb6066::getLoader();

View File

@@ -7,7 +7,162 @@ $baseDir = dirname($vendorDir);
return array(
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Carbon\\AbstractTranslator' => $vendorDir . '/nesbot/carbon/src/Carbon/AbstractTranslator.php',
'Carbon\\Callback' => $vendorDir . '/nesbot/carbon/src/Carbon/Callback.php',
'Carbon\\Carbon' => $vendorDir . '/nesbot/carbon/src/Carbon/Carbon.php',
'Carbon\\CarbonConverterInterface' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonConverterInterface.php',
'Carbon\\CarbonImmutable' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonImmutable.php',
'Carbon\\CarbonInterface' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonInterface.php',
'Carbon\\CarbonInterval' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonInterval.php',
'Carbon\\CarbonPeriod' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonPeriod.php',
'Carbon\\CarbonPeriodImmutable' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonPeriodImmutable.php',
'Carbon\\CarbonTimeZone' => $vendorDir . '/nesbot/carbon/src/Carbon/CarbonTimeZone.php',
'Carbon\\Cli\\Invoker' => $vendorDir . '/nesbot/carbon/src/Carbon/Cli/Invoker.php',
'Carbon\\Constants\\DiffOptions' => $vendorDir . '/nesbot/carbon/src/Carbon/Constants/DiffOptions.php',
'Carbon\\Constants\\Format' => $vendorDir . '/nesbot/carbon/src/Carbon/Constants/Format.php',
'Carbon\\Constants\\TranslationOptions' => $vendorDir . '/nesbot/carbon/src/Carbon/Constants/TranslationOptions.php',
'Carbon\\Constants\\UnitValue' => $vendorDir . '/nesbot/carbon/src/Carbon/Constants/UnitValue.php',
'Carbon\\Doctrine\\CarbonDoctrineType' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonDoctrineType.php',
'Carbon\\Doctrine\\CarbonImmutableType' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonImmutableType.php',
'Carbon\\Doctrine\\CarbonType' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonType.php',
'Carbon\\Doctrine\\CarbonTypeConverter' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonTypeConverter.php',
'Carbon\\Doctrine\\DateTimeDefaultPrecision' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeDefaultPrecision.php',
'Carbon\\Doctrine\\DateTimeImmutableType' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeImmutableType.php',
'Carbon\\Doctrine\\DateTimeType' => $vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeType.php',
'Carbon\\Exceptions\\BadComparisonUnitException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/BadComparisonUnitException.php',
'Carbon\\Exceptions\\BadFluentConstructorException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/BadFluentConstructorException.php',
'Carbon\\Exceptions\\BadFluentSetterException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/BadFluentSetterException.php',
'Carbon\\Exceptions\\BadMethodCallException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/BadMethodCallException.php',
'Carbon\\Exceptions\\EndLessPeriodException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/EndLessPeriodException.php',
'Carbon\\Exceptions\\Exception' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/Exception.php',
'Carbon\\Exceptions\\ImmutableException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/ImmutableException.php',
'Carbon\\Exceptions\\InvalidArgumentException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidArgumentException.php',
'Carbon\\Exceptions\\InvalidCastException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidCastException.php',
'Carbon\\Exceptions\\InvalidDateException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php',
'Carbon\\Exceptions\\InvalidFormatException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidFormatException.php',
'Carbon\\Exceptions\\InvalidIntervalException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidIntervalException.php',
'Carbon\\Exceptions\\InvalidPeriodDateException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodDateException.php',
'Carbon\\Exceptions\\InvalidPeriodParameterException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidPeriodParameterException.php',
'Carbon\\Exceptions\\InvalidTimeZoneException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidTimeZoneException.php',
'Carbon\\Exceptions\\InvalidTypeException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/InvalidTypeException.php',
'Carbon\\Exceptions\\NotACarbonClassException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/NotACarbonClassException.php',
'Carbon\\Exceptions\\NotAPeriodException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/NotAPeriodException.php',
'Carbon\\Exceptions\\NotLocaleAwareException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/NotLocaleAwareException.php',
'Carbon\\Exceptions\\OutOfRangeException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/OutOfRangeException.php',
'Carbon\\Exceptions\\ParseErrorException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/ParseErrorException.php',
'Carbon\\Exceptions\\RuntimeException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/RuntimeException.php',
'Carbon\\Exceptions\\UnitException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnitException.php',
'Carbon\\Exceptions\\UnitNotConfiguredException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnitNotConfiguredException.php',
'Carbon\\Exceptions\\UnknownGetterException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnknownGetterException.php',
'Carbon\\Exceptions\\UnknownMethodException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnknownMethodException.php',
'Carbon\\Exceptions\\UnknownSetterException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnknownSetterException.php',
'Carbon\\Exceptions\\UnknownUnitException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnknownUnitException.php',
'Carbon\\Exceptions\\UnreachableException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnreachableException.php',
'Carbon\\Exceptions\\UnsupportedUnitException' => $vendorDir . '/nesbot/carbon/src/Carbon/Exceptions/UnsupportedUnitException.php',
'Carbon\\Factory' => $vendorDir . '/nesbot/carbon/src/Carbon/Factory.php',
'Carbon\\FactoryImmutable' => $vendorDir . '/nesbot/carbon/src/Carbon/FactoryImmutable.php',
'Carbon\\Language' => $vendorDir . '/nesbot/carbon/src/Carbon/Language.php',
'Carbon\\Laravel\\ServiceProvider' => $vendorDir . '/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php',
'Carbon\\MessageFormatter\\MessageFormatterMapper' => $vendorDir . '/nesbot/carbon/src/Carbon/MessageFormatter/MessageFormatterMapper.php',
'Carbon\\Month' => $vendorDir . '/nesbot/carbon/src/Carbon/Month.php',
'Carbon\\OverflowMode' => $vendorDir . '/nesbot/carbon/src/Carbon/OverflowMode.php',
'Carbon\\PHPStan\\MacroExtension' => $vendorDir . '/nesbot/carbon/src/Carbon/PHPStan/MacroExtension.php',
'Carbon\\PHPStan\\MacroMethodReflection' => $vendorDir . '/nesbot/carbon/src/Carbon/PHPStan/MacroMethodReflection.php',
'Carbon\\Traits\\Boundaries' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Boundaries.php',
'Carbon\\Traits\\Cast' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Cast.php',
'Carbon\\Traits\\Comparison' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Comparison.php',
'Carbon\\Traits\\Converter' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Converter.php',
'Carbon\\Traits\\Creator' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Creator.php',
'Carbon\\Traits\\Date' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Date.php',
'Carbon\\Traits\\DeprecatedPeriodProperties' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/DeprecatedPeriodProperties.php',
'Carbon\\Traits\\Difference' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Difference.php',
'Carbon\\Traits\\IntervalRounding' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/IntervalRounding.php',
'Carbon\\Traits\\IntervalStep' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/IntervalStep.php',
'Carbon\\Traits\\LocalFactory' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/LocalFactory.php',
'Carbon\\Traits\\Localization' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Localization.php',
'Carbon\\Traits\\Macro' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Macro.php',
'Carbon\\Traits\\MagicParameter' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/MagicParameter.php',
'Carbon\\Traits\\Mixin' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Mixin.php',
'Carbon\\Traits\\Modifiers' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Modifiers.php',
'Carbon\\Traits\\Mutability' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Mutability.php',
'Carbon\\Traits\\ObjectInitialisation' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/ObjectInitialisation.php',
'Carbon\\Traits\\Options' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Options.php',
'Carbon\\Traits\\Rounding' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Rounding.php',
'Carbon\\Traits\\Serialization' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Serialization.php',
'Carbon\\Traits\\StaticLocalization' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/StaticLocalization.php',
'Carbon\\Traits\\StaticOptions' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/StaticOptions.php',
'Carbon\\Traits\\Test' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Test.php',
'Carbon\\Traits\\Timestamp' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Timestamp.php',
'Carbon\\Traits\\ToStringFormat' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/ToStringFormat.php',
'Carbon\\Traits\\Units' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Units.php',
'Carbon\\Traits\\Week' => $vendorDir . '/nesbot/carbon/src/Carbon/Traits/Week.php',
'Carbon\\Translator' => $vendorDir . '/nesbot/carbon/src/Carbon/Translator.php',
'Carbon\\TranslatorImmutable' => $vendorDir . '/nesbot/carbon/src/Carbon/TranslatorImmutable.php',
'Carbon\\TranslatorStrongTypeInterface' => $vendorDir . '/nesbot/carbon/src/Carbon/TranslatorStrongTypeInterface.php',
'Carbon\\Unit' => $vendorDir . '/nesbot/carbon/src/Carbon/Unit.php',
'Carbon\\WeekDay' => $vendorDir . '/nesbot/carbon/src/Carbon/WeekDay.php',
'Carbon\\WrapperClock' => $vendorDir . '/nesbot/carbon/src/Carbon/WrapperClock.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'DI\\Attribute\\Inject' => $vendorDir . '/php-di/php-di/src/Attribute/Inject.php',
'DI\\Attribute\\Injectable' => $vendorDir . '/php-di/php-di/src/Attribute/Injectable.php',
'DI\\CompiledContainer' => $vendorDir . '/php-di/php-di/src/CompiledContainer.php',
'DI\\Compiler\\Compiler' => $vendorDir . '/php-di/php-di/src/Compiler/Compiler.php',
'DI\\Compiler\\ObjectCreationCompiler' => $vendorDir . '/php-di/php-di/src/Compiler/ObjectCreationCompiler.php',
'DI\\Compiler\\RequestedEntryHolder' => $vendorDir . '/php-di/php-di/src/Compiler/RequestedEntryHolder.php',
'DI\\Container' => $vendorDir . '/php-di/php-di/src/Container.php',
'DI\\ContainerBuilder' => $vendorDir . '/php-di/php-di/src/ContainerBuilder.php',
'DI\\Definition\\ArrayDefinition' => $vendorDir . '/php-di/php-di/src/Definition/ArrayDefinition.php',
'DI\\Definition\\ArrayDefinitionExtension' => $vendorDir . '/php-di/php-di/src/Definition/ArrayDefinitionExtension.php',
'DI\\Definition\\AutowireDefinition' => $vendorDir . '/php-di/php-di/src/Definition/AutowireDefinition.php',
'DI\\Definition\\DecoratorDefinition' => $vendorDir . '/php-di/php-di/src/Definition/DecoratorDefinition.php',
'DI\\Definition\\Definition' => $vendorDir . '/php-di/php-di/src/Definition/Definition.php',
'DI\\Definition\\Dumper\\ObjectDefinitionDumper' => $vendorDir . '/php-di/php-di/src/Definition/Dumper/ObjectDefinitionDumper.php',
'DI\\Definition\\EnvironmentVariableDefinition' => $vendorDir . '/php-di/php-di/src/Definition/EnvironmentVariableDefinition.php',
'DI\\Definition\\Exception\\InvalidAttribute' => $vendorDir . '/php-di/php-di/src/Definition/Exception/InvalidAttribute.php',
'DI\\Definition\\Exception\\InvalidDefinition' => $vendorDir . '/php-di/php-di/src/Definition/Exception/InvalidDefinition.php',
'DI\\Definition\\ExtendsPreviousDefinition' => $vendorDir . '/php-di/php-di/src/Definition/ExtendsPreviousDefinition.php',
'DI\\Definition\\FactoryDefinition' => $vendorDir . '/php-di/php-di/src/Definition/FactoryDefinition.php',
'DI\\Definition\\Helper\\AutowireDefinitionHelper' => $vendorDir . '/php-di/php-di/src/Definition/Helper/AutowireDefinitionHelper.php',
'DI\\Definition\\Helper\\CreateDefinitionHelper' => $vendorDir . '/php-di/php-di/src/Definition/Helper/CreateDefinitionHelper.php',
'DI\\Definition\\Helper\\DefinitionHelper' => $vendorDir . '/php-di/php-di/src/Definition/Helper/DefinitionHelper.php',
'DI\\Definition\\Helper\\FactoryDefinitionHelper' => $vendorDir . '/php-di/php-di/src/Definition/Helper/FactoryDefinitionHelper.php',
'DI\\Definition\\InstanceDefinition' => $vendorDir . '/php-di/php-di/src/Definition/InstanceDefinition.php',
'DI\\Definition\\ObjectDefinition' => $vendorDir . '/php-di/php-di/src/Definition/ObjectDefinition.php',
'DI\\Definition\\ObjectDefinition\\MethodInjection' => $vendorDir . '/php-di/php-di/src/Definition/ObjectDefinition/MethodInjection.php',
'DI\\Definition\\ObjectDefinition\\PropertyInjection' => $vendorDir . '/php-di/php-di/src/Definition/ObjectDefinition/PropertyInjection.php',
'DI\\Definition\\Reference' => $vendorDir . '/php-di/php-di/src/Definition/Reference.php',
'DI\\Definition\\Resolver\\ArrayResolver' => $vendorDir . '/php-di/php-di/src/Definition/Resolver/ArrayResolver.php',
'DI\\Definition\\Resolver\\DecoratorResolver' => $vendorDir . '/php-di/php-di/src/Definition/Resolver/DecoratorResolver.php',
'DI\\Definition\\Resolver\\DefinitionResolver' => $vendorDir . '/php-di/php-di/src/Definition/Resolver/DefinitionResolver.php',
'DI\\Definition\\Resolver\\EnvironmentVariableResolver' => $vendorDir . '/php-di/php-di/src/Definition/Resolver/EnvironmentVariableResolver.php',
'DI\\Definition\\Resolver\\FactoryResolver' => $vendorDir . '/php-di/php-di/src/Definition/Resolver/FactoryResolver.php',
'DI\\Definition\\Resolver\\InstanceInjector' => $vendorDir . '/php-di/php-di/src/Definition/Resolver/InstanceInjector.php',
'DI\\Definition\\Resolver\\ObjectCreator' => $vendorDir . '/php-di/php-di/src/Definition/Resolver/ObjectCreator.php',
'DI\\Definition\\Resolver\\ParameterResolver' => $vendorDir . '/php-di/php-di/src/Definition/Resolver/ParameterResolver.php',
'DI\\Definition\\Resolver\\ResolverDispatcher' => $vendorDir . '/php-di/php-di/src/Definition/Resolver/ResolverDispatcher.php',
'DI\\Definition\\SelfResolvingDefinition' => $vendorDir . '/php-di/php-di/src/Definition/SelfResolvingDefinition.php',
'DI\\Definition\\Source\\AttributeBasedAutowiring' => $vendorDir . '/php-di/php-di/src/Definition/Source/AttributeBasedAutowiring.php',
'DI\\Definition\\Source\\Autowiring' => $vendorDir . '/php-di/php-di/src/Definition/Source/Autowiring.php',
'DI\\Definition\\Source\\DefinitionArray' => $vendorDir . '/php-di/php-di/src/Definition/Source/DefinitionArray.php',
'DI\\Definition\\Source\\DefinitionFile' => $vendorDir . '/php-di/php-di/src/Definition/Source/DefinitionFile.php',
'DI\\Definition\\Source\\DefinitionNormalizer' => $vendorDir . '/php-di/php-di/src/Definition/Source/DefinitionNormalizer.php',
'DI\\Definition\\Source\\DefinitionSource' => $vendorDir . '/php-di/php-di/src/Definition/Source/DefinitionSource.php',
'DI\\Definition\\Source\\MutableDefinitionSource' => $vendorDir . '/php-di/php-di/src/Definition/Source/MutableDefinitionSource.php',
'DI\\Definition\\Source\\NoAutowiring' => $vendorDir . '/php-di/php-di/src/Definition/Source/NoAutowiring.php',
'DI\\Definition\\Source\\ReflectionBasedAutowiring' => $vendorDir . '/php-di/php-di/src/Definition/Source/ReflectionBasedAutowiring.php',
'DI\\Definition\\Source\\SourceCache' => $vendorDir . '/php-di/php-di/src/Definition/Source/SourceCache.php',
'DI\\Definition\\Source\\SourceChain' => $vendorDir . '/php-di/php-di/src/Definition/Source/SourceChain.php',
'DI\\Definition\\StringDefinition' => $vendorDir . '/php-di/php-di/src/Definition/StringDefinition.php',
'DI\\Definition\\ValueDefinition' => $vendorDir . '/php-di/php-di/src/Definition/ValueDefinition.php',
'DI\\DependencyException' => $vendorDir . '/php-di/php-di/src/DependencyException.php',
'DI\\FactoryInterface' => $vendorDir . '/php-di/php-di/src/FactoryInterface.php',
'DI\\Factory\\RequestedEntry' => $vendorDir . '/php-di/php-di/src/Factory/RequestedEntry.php',
'DI\\Invoker\\DefinitionParameterResolver' => $vendorDir . '/php-di/php-di/src/Invoker/DefinitionParameterResolver.php',
'DI\\Invoker\\FactoryParameterResolver' => $vendorDir . '/php-di/php-di/src/Invoker/FactoryParameterResolver.php',
'DI\\NotFoundException' => $vendorDir . '/php-di/php-di/src/NotFoundException.php',
'DI\\Proxy\\NativeProxyFactory' => $vendorDir . '/php-di/php-di/src/Proxy/NativeProxyFactory.php',
'DI\\Proxy\\ProxyFactory' => $vendorDir . '/php-di/php-di/src/Proxy/ProxyFactory.php',
'DI\\Proxy\\ProxyFactoryInterface' => $vendorDir . '/php-di/php-di/src/Proxy/ProxyFactoryInterface.php',
'DateError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateError.php',
'DateException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateException.php',
'DateInvalidOperationException' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.php',
@@ -19,8 +174,413 @@ return array(
'DateRangeError' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/DateRangeError.php',
'DelayedTargetValidation' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/DelayedTargetValidation.php',
'Deprecated' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Deprecated.php',
'DirectoryTree\\ImapEngine\\Address' => $vendorDir . '/directorytree/imapengine/src/Address.php',
'DirectoryTree\\ImapEngine\\Attachment' => $vendorDir . '/directorytree/imapengine/src/Attachment.php',
'DirectoryTree\\ImapEngine\\BodyStructureCollection' => $vendorDir . '/directorytree/imapengine/src/BodyStructureCollection.php',
'DirectoryTree\\ImapEngine\\BodyStructurePart' => $vendorDir . '/directorytree/imapengine/src/BodyStructurePart.php',
'DirectoryTree\\ImapEngine\\Collections\\FolderCollection' => $vendorDir . '/directorytree/imapengine/src/Collections/FolderCollection.php',
'DirectoryTree\\ImapEngine\\Collections\\MessageCollection' => $vendorDir . '/directorytree/imapengine/src/Collections/MessageCollection.php',
'DirectoryTree\\ImapEngine\\Collections\\PaginatedCollection' => $vendorDir . '/directorytree/imapengine/src/Collections/PaginatedCollection.php',
'DirectoryTree\\ImapEngine\\Collections\\ResponseCollection' => $vendorDir . '/directorytree/imapengine/src/Collections/ResponseCollection.php',
'DirectoryTree\\ImapEngine\\ComparesFolders' => $vendorDir . '/directorytree/imapengine/src/ComparesFolders.php',
'DirectoryTree\\ImapEngine\\Connection\\ConnectionInterface' => $vendorDir . '/directorytree/imapengine/src/Connection/ConnectionInterface.php',
'DirectoryTree\\ImapEngine\\Connection\\ImapCommand' => $vendorDir . '/directorytree/imapengine/src/Connection/ImapCommand.php',
'DirectoryTree\\ImapEngine\\Connection\\ImapConnection' => $vendorDir . '/directorytree/imapengine/src/Connection/ImapConnection.php',
'DirectoryTree\\ImapEngine\\Connection\\ImapParser' => $vendorDir . '/directorytree/imapengine/src/Connection/ImapParser.php',
'DirectoryTree\\ImapEngine\\Connection\\ImapQueryBuilder' => $vendorDir . '/directorytree/imapengine/src/Connection/ImapQueryBuilder.php',
'DirectoryTree\\ImapEngine\\Connection\\ImapTokenizer' => $vendorDir . '/directorytree/imapengine/src/Connection/ImapTokenizer.php',
'DirectoryTree\\ImapEngine\\Connection\\Loggers\\EchoLogger' => $vendorDir . '/directorytree/imapengine/src/Connection/Loggers/EchoLogger.php',
'DirectoryTree\\ImapEngine\\Connection\\Loggers\\FileLogger' => $vendorDir . '/directorytree/imapengine/src/Connection/Loggers/FileLogger.php',
'DirectoryTree\\ImapEngine\\Connection\\Loggers\\Logger' => $vendorDir . '/directorytree/imapengine/src/Connection/Loggers/Logger.php',
'DirectoryTree\\ImapEngine\\Connection\\Loggers\\LoggerInterface' => $vendorDir . '/directorytree/imapengine/src/Connection/Loggers/LoggerInterface.php',
'DirectoryTree\\ImapEngine\\Connection\\Loggers\\RayLogger' => $vendorDir . '/directorytree/imapengine/src/Connection/Loggers/RayLogger.php',
'DirectoryTree\\ImapEngine\\Connection\\RawQueryValue' => $vendorDir . '/directorytree/imapengine/src/Connection/RawQueryValue.php',
'DirectoryTree\\ImapEngine\\Connection\\Responses\\ContinuationResponse' => $vendorDir . '/directorytree/imapengine/src/Connection/Responses/ContinuationResponse.php',
'DirectoryTree\\ImapEngine\\Connection\\Responses\\Data\\Data' => $vendorDir . '/directorytree/imapengine/src/Connection/Responses/Data/Data.php',
'DirectoryTree\\ImapEngine\\Connection\\Responses\\Data\\ListData' => $vendorDir . '/directorytree/imapengine/src/Connection/Responses/Data/ListData.php',
'DirectoryTree\\ImapEngine\\Connection\\Responses\\Data\\ResponseCodeData' => $vendorDir . '/directorytree/imapengine/src/Connection/Responses/Data/ResponseCodeData.php',
'DirectoryTree\\ImapEngine\\Connection\\Responses\\HasTokens' => $vendorDir . '/directorytree/imapengine/src/Connection/Responses/HasTokens.php',
'DirectoryTree\\ImapEngine\\Connection\\Responses\\MessageResponseParser' => $vendorDir . '/directorytree/imapengine/src/Connection/Responses/MessageResponseParser.php',
'DirectoryTree\\ImapEngine\\Connection\\Responses\\Response' => $vendorDir . '/directorytree/imapengine/src/Connection/Responses/Response.php',
'DirectoryTree\\ImapEngine\\Connection\\Responses\\TaggedResponse' => $vendorDir . '/directorytree/imapengine/src/Connection/Responses/TaggedResponse.php',
'DirectoryTree\\ImapEngine\\Connection\\Responses\\UntaggedResponse' => $vendorDir . '/directorytree/imapengine/src/Connection/Responses/UntaggedResponse.php',
'DirectoryTree\\ImapEngine\\Connection\\Result' => $vendorDir . '/directorytree/imapengine/src/Connection/Result.php',
'DirectoryTree\\ImapEngine\\Connection\\Streams\\FakeStream' => $vendorDir . '/directorytree/imapengine/src/Connection/Streams/FakeStream.php',
'DirectoryTree\\ImapEngine\\Connection\\Streams\\ImapStream' => $vendorDir . '/directorytree/imapengine/src/Connection/Streams/ImapStream.php',
'DirectoryTree\\ImapEngine\\Connection\\Streams\\StreamInterface' => $vendorDir . '/directorytree/imapengine/src/Connection/Streams/StreamInterface.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\Atom' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/Atom.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\Crlf' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/Crlf.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\EmailAddress' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/EmailAddress.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\ListClose' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/ListClose.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\ListOpen' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/ListOpen.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\Literal' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/Literal.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\Nil' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/Nil.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\Number' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/Number.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\QuotedString' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/QuotedString.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\ResponseCodeClose' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/ResponseCodeClose.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\ResponseCodeOpen' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/ResponseCodeOpen.php',
'DirectoryTree\\ImapEngine\\Connection\\Tokens\\Token' => $vendorDir . '/directorytree/imapengine/src/Connection/Tokens/Token.php',
'DirectoryTree\\ImapEngine\\ContentDisposition' => $vendorDir . '/directorytree/imapengine/src/ContentDisposition.php',
'DirectoryTree\\ImapEngine\\DraftMessage' => $vendorDir . '/directorytree/imapengine/src/DraftMessage.php',
'DirectoryTree\\ImapEngine\\Enums\\ContentDispositionType' => $vendorDir . '/directorytree/imapengine/src/Enums/ContentDispositionType.php',
'DirectoryTree\\ImapEngine\\Enums\\ImapFetchIdentifier' => $vendorDir . '/directorytree/imapengine/src/Enums/ImapFetchIdentifier.php',
'DirectoryTree\\ImapEngine\\Enums\\ImapFlag' => $vendorDir . '/directorytree/imapengine/src/Enums/ImapFlag.php',
'DirectoryTree\\ImapEngine\\Enums\\ImapSearchKey' => $vendorDir . '/directorytree/imapengine/src/Enums/ImapSearchKey.php',
'DirectoryTree\\ImapEngine\\Enums\\ImapSortKey' => $vendorDir . '/directorytree/imapengine/src/Enums/ImapSortKey.php',
'DirectoryTree\\ImapEngine\\Exceptions\\Exception' => $vendorDir . '/directorytree/imapengine/src/Exceptions/Exception.php',
'DirectoryTree\\ImapEngine\\Exceptions\\ImapCapabilityException' => $vendorDir . '/directorytree/imapengine/src/Exceptions/ImapCapabilityException.php',
'DirectoryTree\\ImapEngine\\Exceptions\\ImapCommandException' => $vendorDir . '/directorytree/imapengine/src/Exceptions/ImapCommandException.php',
'DirectoryTree\\ImapEngine\\Exceptions\\ImapConnectionClosedException' => $vendorDir . '/directorytree/imapengine/src/Exceptions/ImapConnectionClosedException.php',
'DirectoryTree\\ImapEngine\\Exceptions\\ImapConnectionException' => $vendorDir . '/directorytree/imapengine/src/Exceptions/ImapConnectionException.php',
'DirectoryTree\\ImapEngine\\Exceptions\\ImapConnectionFailedException' => $vendorDir . '/directorytree/imapengine/src/Exceptions/ImapConnectionFailedException.php',
'DirectoryTree\\ImapEngine\\Exceptions\\ImapConnectionTimedOutException' => $vendorDir . '/directorytree/imapengine/src/Exceptions/ImapConnectionTimedOutException.php',
'DirectoryTree\\ImapEngine\\Exceptions\\ImapParserException' => $vendorDir . '/directorytree/imapengine/src/Exceptions/ImapParserException.php',
'DirectoryTree\\ImapEngine\\Exceptions\\ImapResponseException' => $vendorDir . '/directorytree/imapengine/src/Exceptions/ImapResponseException.php',
'DirectoryTree\\ImapEngine\\Exceptions\\ImapStreamException' => $vendorDir . '/directorytree/imapengine/src/Exceptions/ImapStreamException.php',
'DirectoryTree\\ImapEngine\\Exceptions\\RuntimeException' => $vendorDir . '/directorytree/imapengine/src/Exceptions/RuntimeException.php',
'DirectoryTree\\ImapEngine\\FileMessage' => $vendorDir . '/directorytree/imapengine/src/FileMessage.php',
'DirectoryTree\\ImapEngine\\FlaggableInterface' => $vendorDir . '/directorytree/imapengine/src/FlaggableInterface.php',
'DirectoryTree\\ImapEngine\\Folder' => $vendorDir . '/directorytree/imapengine/src/Folder.php',
'DirectoryTree\\ImapEngine\\FolderInterface' => $vendorDir . '/directorytree/imapengine/src/FolderInterface.php',
'DirectoryTree\\ImapEngine\\FolderRepository' => $vendorDir . '/directorytree/imapengine/src/FolderRepository.php',
'DirectoryTree\\ImapEngine\\FolderRepositoryInterface' => $vendorDir . '/directorytree/imapengine/src/FolderRepositoryInterface.php',
'DirectoryTree\\ImapEngine\\HasFlags' => $vendorDir . '/directorytree/imapengine/src/HasFlags.php',
'DirectoryTree\\ImapEngine\\HasMessageAccessors' => $vendorDir . '/directorytree/imapengine/src/HasMessageAccessors.php',
'DirectoryTree\\ImapEngine\\HasParsedMessage' => $vendorDir . '/directorytree/imapengine/src/HasParsedMessage.php',
'DirectoryTree\\ImapEngine\\Idle' => $vendorDir . '/directorytree/imapengine/src/Idle.php',
'DirectoryTree\\ImapEngine\\Mailbox' => $vendorDir . '/directorytree/imapengine/src/Mailbox.php',
'DirectoryTree\\ImapEngine\\MailboxInterface' => $vendorDir . '/directorytree/imapengine/src/MailboxInterface.php',
'DirectoryTree\\ImapEngine\\Mbox' => $vendorDir . '/directorytree/imapengine/src/Mbox.php',
'DirectoryTree\\ImapEngine\\Message' => $vendorDir . '/directorytree/imapengine/src/Message.php',
'DirectoryTree\\ImapEngine\\MessageInterface' => $vendorDir . '/directorytree/imapengine/src/MessageInterface.php',
'DirectoryTree\\ImapEngine\\MessageParser' => $vendorDir . '/directorytree/imapengine/src/MessageParser.php',
'DirectoryTree\\ImapEngine\\MessageQuery' => $vendorDir . '/directorytree/imapengine/src/MessageQuery.php',
'DirectoryTree\\ImapEngine\\MessageQueryInterface' => $vendorDir . '/directorytree/imapengine/src/MessageQueryInterface.php',
'DirectoryTree\\ImapEngine\\Pagination\\LengthAwarePaginator' => $vendorDir . '/directorytree/imapengine/src/Pagination/LengthAwarePaginator.php',
'DirectoryTree\\ImapEngine\\Poll' => $vendorDir . '/directorytree/imapengine/src/Poll.php',
'DirectoryTree\\ImapEngine\\QueriesMessages' => $vendorDir . '/directorytree/imapengine/src/QueriesMessages.php',
'DirectoryTree\\ImapEngine\\Support\\BodyPartDecoder' => $vendorDir . '/directorytree/imapengine/src/Support/BodyPartDecoder.php',
'DirectoryTree\\ImapEngine\\Support\\ForwardsCalls' => $vendorDir . '/directorytree/imapengine/src/Support/ForwardsCalls.php',
'DirectoryTree\\ImapEngine\\Support\\LazyBodyPartStream' => $vendorDir . '/directorytree/imapengine/src/Support/LazyBodyPartStream.php',
'DirectoryTree\\ImapEngine\\Support\\MimeMessage' => $vendorDir . '/directorytree/imapengine/src/Support/MimeMessage.php',
'DirectoryTree\\ImapEngine\\Support\\Str' => $vendorDir . '/directorytree/imapengine/src/Support/Str.php',
'DirectoryTree\\ImapEngine\\Testing\\FakeFolder' => $vendorDir . '/directorytree/imapengine/src/Testing/FakeFolder.php',
'DirectoryTree\\ImapEngine\\Testing\\FakeFolderRepository' => $vendorDir . '/directorytree/imapengine/src/Testing/FakeFolderRepository.php',
'DirectoryTree\\ImapEngine\\Testing\\FakeMailbox' => $vendorDir . '/directorytree/imapengine/src/Testing/FakeMailbox.php',
'DirectoryTree\\ImapEngine\\Testing\\FakeMessage' => $vendorDir . '/directorytree/imapengine/src/Testing/FakeMessage.php',
'DirectoryTree\\ImapEngine\\Testing\\FakeMessageQuery' => $vendorDir . '/directorytree/imapengine/src/Testing/FakeMessageQuery.php',
'Doctrine\\Common\\Lexer\\AbstractLexer' => $vendorDir . '/doctrine/lexer/src/AbstractLexer.php',
'Doctrine\\Common\\Lexer\\Token' => $vendorDir . '/doctrine/lexer/src/Token.php',
'Egulias\\EmailValidator\\EmailLexer' => $vendorDir . '/egulias/email-validator/src/EmailLexer.php',
'Egulias\\EmailValidator\\EmailParser' => $vendorDir . '/egulias/email-validator/src/EmailParser.php',
'Egulias\\EmailValidator\\EmailValidator' => $vendorDir . '/egulias/email-validator/src/EmailValidator.php',
'Egulias\\EmailValidator\\MessageIDParser' => $vendorDir . '/egulias/email-validator/src/MessageIDParser.php',
'Egulias\\EmailValidator\\Parser' => $vendorDir . '/egulias/email-validator/src/Parser.php',
'Egulias\\EmailValidator\\Parser\\Comment' => $vendorDir . '/egulias/email-validator/src/Parser/Comment.php',
'Egulias\\EmailValidator\\Parser\\CommentStrategy\\CommentStrategy' => $vendorDir . '/egulias/email-validator/src/Parser/CommentStrategy/CommentStrategy.php',
'Egulias\\EmailValidator\\Parser\\CommentStrategy\\DomainComment' => $vendorDir . '/egulias/email-validator/src/Parser/CommentStrategy/DomainComment.php',
'Egulias\\EmailValidator\\Parser\\CommentStrategy\\LocalComment' => $vendorDir . '/egulias/email-validator/src/Parser/CommentStrategy/LocalComment.php',
'Egulias\\EmailValidator\\Parser\\DomainLiteral' => $vendorDir . '/egulias/email-validator/src/Parser/DomainLiteral.php',
'Egulias\\EmailValidator\\Parser\\DomainPart' => $vendorDir . '/egulias/email-validator/src/Parser/DomainPart.php',
'Egulias\\EmailValidator\\Parser\\DoubleQuote' => $vendorDir . '/egulias/email-validator/src/Parser/DoubleQuote.php',
'Egulias\\EmailValidator\\Parser\\FoldingWhiteSpace' => $vendorDir . '/egulias/email-validator/src/Parser/FoldingWhiteSpace.php',
'Egulias\\EmailValidator\\Parser\\IDLeftPart' => $vendorDir . '/egulias/email-validator/src/Parser/IDLeftPart.php',
'Egulias\\EmailValidator\\Parser\\IDRightPart' => $vendorDir . '/egulias/email-validator/src/Parser/IDRightPart.php',
'Egulias\\EmailValidator\\Parser\\LocalPart' => $vendorDir . '/egulias/email-validator/src/Parser/LocalPart.php',
'Egulias\\EmailValidator\\Parser\\PartParser' => $vendorDir . '/egulias/email-validator/src/Parser/PartParser.php',
'Egulias\\EmailValidator\\Result\\InvalidEmail' => $vendorDir . '/egulias/email-validator/src/Result/InvalidEmail.php',
'Egulias\\EmailValidator\\Result\\MultipleErrors' => $vendorDir . '/egulias/email-validator/src/Result/MultipleErrors.php',
'Egulias\\EmailValidator\\Result\\Reason\\AtextAfterCFWS' => $vendorDir . '/egulias/email-validator/src/Result/Reason/AtextAfterCFWS.php',
'Egulias\\EmailValidator\\Result\\Reason\\CRLFAtTheEnd' => $vendorDir . '/egulias/email-validator/src/Result/Reason/CRLFAtTheEnd.php',
'Egulias\\EmailValidator\\Result\\Reason\\CRLFX2' => $vendorDir . '/egulias/email-validator/src/Result/Reason/CRLFX2.php',
'Egulias\\EmailValidator\\Result\\Reason\\CRNoLF' => $vendorDir . '/egulias/email-validator/src/Result/Reason/CRNoLF.php',
'Egulias\\EmailValidator\\Result\\Reason\\CharNotAllowed' => $vendorDir . '/egulias/email-validator/src/Result/Reason/CharNotAllowed.php',
'Egulias\\EmailValidator\\Result\\Reason\\CommaInDomain' => $vendorDir . '/egulias/email-validator/src/Result/Reason/CommaInDomain.php',
'Egulias\\EmailValidator\\Result\\Reason\\CommentsInIDRight' => $vendorDir . '/egulias/email-validator/src/Result/Reason/CommentsInIDRight.php',
'Egulias\\EmailValidator\\Result\\Reason\\ConsecutiveAt' => $vendorDir . '/egulias/email-validator/src/Result/Reason/ConsecutiveAt.php',
'Egulias\\EmailValidator\\Result\\Reason\\ConsecutiveDot' => $vendorDir . '/egulias/email-validator/src/Result/Reason/ConsecutiveDot.php',
'Egulias\\EmailValidator\\Result\\Reason\\DetailedReason' => $vendorDir . '/egulias/email-validator/src/Result/Reason/DetailedReason.php',
'Egulias\\EmailValidator\\Result\\Reason\\DomainAcceptsNoMail' => $vendorDir . '/egulias/email-validator/src/Result/Reason/DomainAcceptsNoMail.php',
'Egulias\\EmailValidator\\Result\\Reason\\DomainHyphened' => $vendorDir . '/egulias/email-validator/src/Result/Reason/DomainHyphened.php',
'Egulias\\EmailValidator\\Result\\Reason\\DomainTooLong' => $vendorDir . '/egulias/email-validator/src/Result/Reason/DomainTooLong.php',
'Egulias\\EmailValidator\\Result\\Reason\\DotAtEnd' => $vendorDir . '/egulias/email-validator/src/Result/Reason/DotAtEnd.php',
'Egulias\\EmailValidator\\Result\\Reason\\DotAtStart' => $vendorDir . '/egulias/email-validator/src/Result/Reason/DotAtStart.php',
'Egulias\\EmailValidator\\Result\\Reason\\EmptyReason' => $vendorDir . '/egulias/email-validator/src/Result/Reason/EmptyReason.php',
'Egulias\\EmailValidator\\Result\\Reason\\ExceptionFound' => $vendorDir . '/egulias/email-validator/src/Result/Reason/ExceptionFound.php',
'Egulias\\EmailValidator\\Result\\Reason\\ExpectingATEXT' => $vendorDir . '/egulias/email-validator/src/Result/Reason/ExpectingATEXT.php',
'Egulias\\EmailValidator\\Result\\Reason\\ExpectingCTEXT' => $vendorDir . '/egulias/email-validator/src/Result/Reason/ExpectingCTEXT.php',
'Egulias\\EmailValidator\\Result\\Reason\\ExpectingDTEXT' => $vendorDir . '/egulias/email-validator/src/Result/Reason/ExpectingDTEXT.php',
'Egulias\\EmailValidator\\Result\\Reason\\ExpectingDomainLiteralClose' => $vendorDir . '/egulias/email-validator/src/Result/Reason/ExpectingDomainLiteralClose.php',
'Egulias\\EmailValidator\\Result\\Reason\\LabelTooLong' => $vendorDir . '/egulias/email-validator/src/Result/Reason/LabelTooLong.php',
'Egulias\\EmailValidator\\Result\\Reason\\LocalOrReservedDomain' => $vendorDir . '/egulias/email-validator/src/Result/Reason/LocalOrReservedDomain.php',
'Egulias\\EmailValidator\\Result\\Reason\\NoDNSRecord' => $vendorDir . '/egulias/email-validator/src/Result/Reason/NoDNSRecord.php',
'Egulias\\EmailValidator\\Result\\Reason\\NoDomainPart' => $vendorDir . '/egulias/email-validator/src/Result/Reason/NoDomainPart.php',
'Egulias\\EmailValidator\\Result\\Reason\\NoLocalPart' => $vendorDir . '/egulias/email-validator/src/Result/Reason/NoLocalPart.php',
'Egulias\\EmailValidator\\Result\\Reason\\RFCWarnings' => $vendorDir . '/egulias/email-validator/src/Result/Reason/RFCWarnings.php',
'Egulias\\EmailValidator\\Result\\Reason\\Reason' => $vendorDir . '/egulias/email-validator/src/Result/Reason/Reason.php',
'Egulias\\EmailValidator\\Result\\Reason\\SpoofEmail' => $vendorDir . '/egulias/email-validator/src/Result/Reason/SpoofEmail.php',
'Egulias\\EmailValidator\\Result\\Reason\\UnOpenedComment' => $vendorDir . '/egulias/email-validator/src/Result/Reason/UnOpenedComment.php',
'Egulias\\EmailValidator\\Result\\Reason\\UnableToGetDNSRecord' => $vendorDir . '/egulias/email-validator/src/Result/Reason/UnableToGetDNSRecord.php',
'Egulias\\EmailValidator\\Result\\Reason\\UnclosedComment' => $vendorDir . '/egulias/email-validator/src/Result/Reason/UnclosedComment.php',
'Egulias\\EmailValidator\\Result\\Reason\\UnclosedQuotedString' => $vendorDir . '/egulias/email-validator/src/Result/Reason/UnclosedQuotedString.php',
'Egulias\\EmailValidator\\Result\\Reason\\UnusualElements' => $vendorDir . '/egulias/email-validator/src/Result/Reason/UnusualElements.php',
'Egulias\\EmailValidator\\Result\\Result' => $vendorDir . '/egulias/email-validator/src/Result/Result.php',
'Egulias\\EmailValidator\\Result\\SpoofEmail' => $vendorDir . '/egulias/email-validator/src/Result/SpoofEmail.php',
'Egulias\\EmailValidator\\Result\\ValidEmail' => $vendorDir . '/egulias/email-validator/src/Result/ValidEmail.php',
'Egulias\\EmailValidator\\Validation\\DNSCheckValidation' => $vendorDir . '/egulias/email-validator/src/Validation/DNSCheckValidation.php',
'Egulias\\EmailValidator\\Validation\\DNSGetRecordWrapper' => $vendorDir . '/egulias/email-validator/src/Validation/DNSGetRecordWrapper.php',
'Egulias\\EmailValidator\\Validation\\DNSRecords' => $vendorDir . '/egulias/email-validator/src/Validation/DNSRecords.php',
'Egulias\\EmailValidator\\Validation\\EmailValidation' => $vendorDir . '/egulias/email-validator/src/Validation/EmailValidation.php',
'Egulias\\EmailValidator\\Validation\\Exception\\EmptyValidationList' => $vendorDir . '/egulias/email-validator/src/Validation/Exception/EmptyValidationList.php',
'Egulias\\EmailValidator\\Validation\\Extra\\SpoofCheckValidation' => $vendorDir . '/egulias/email-validator/src/Validation/Extra/SpoofCheckValidation.php',
'Egulias\\EmailValidator\\Validation\\MessageIDValidation' => $vendorDir . '/egulias/email-validator/src/Validation/MessageIDValidation.php',
'Egulias\\EmailValidator\\Validation\\MultipleValidationWithAnd' => $vendorDir . '/egulias/email-validator/src/Validation/MultipleValidationWithAnd.php',
'Egulias\\EmailValidator\\Validation\\NoRFCWarningsValidation' => $vendorDir . '/egulias/email-validator/src/Validation/NoRFCWarningsValidation.php',
'Egulias\\EmailValidator\\Validation\\RFCValidation' => $vendorDir . '/egulias/email-validator/src/Validation/RFCValidation.php',
'Egulias\\EmailValidator\\Warning\\AddressLiteral' => $vendorDir . '/egulias/email-validator/src/Warning/AddressLiteral.php',
'Egulias\\EmailValidator\\Warning\\CFWSNearAt' => $vendorDir . '/egulias/email-validator/src/Warning/CFWSNearAt.php',
'Egulias\\EmailValidator\\Warning\\CFWSWithFWS' => $vendorDir . '/egulias/email-validator/src/Warning/CFWSWithFWS.php',
'Egulias\\EmailValidator\\Warning\\Comment' => $vendorDir . '/egulias/email-validator/src/Warning/Comment.php',
'Egulias\\EmailValidator\\Warning\\DeprecatedComment' => $vendorDir . '/egulias/email-validator/src/Warning/DeprecatedComment.php',
'Egulias\\EmailValidator\\Warning\\DomainLiteral' => $vendorDir . '/egulias/email-validator/src/Warning/DomainLiteral.php',
'Egulias\\EmailValidator\\Warning\\EmailTooLong' => $vendorDir . '/egulias/email-validator/src/Warning/EmailTooLong.php',
'Egulias\\EmailValidator\\Warning\\IPV6BadChar' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6BadChar.php',
'Egulias\\EmailValidator\\Warning\\IPV6ColonEnd' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6ColonEnd.php',
'Egulias\\EmailValidator\\Warning\\IPV6ColonStart' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6ColonStart.php',
'Egulias\\EmailValidator\\Warning\\IPV6Deprecated' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6Deprecated.php',
'Egulias\\EmailValidator\\Warning\\IPV6DoubleColon' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6DoubleColon.php',
'Egulias\\EmailValidator\\Warning\\IPV6GroupCount' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6GroupCount.php',
'Egulias\\EmailValidator\\Warning\\IPV6MaxGroups' => $vendorDir . '/egulias/email-validator/src/Warning/IPV6MaxGroups.php',
'Egulias\\EmailValidator\\Warning\\LocalTooLong' => $vendorDir . '/egulias/email-validator/src/Warning/LocalTooLong.php',
'Egulias\\EmailValidator\\Warning\\NoDNSMXRecord' => $vendorDir . '/egulias/email-validator/src/Warning/NoDNSMXRecord.php',
'Egulias\\EmailValidator\\Warning\\ObsoleteDTEXT' => $vendorDir . '/egulias/email-validator/src/Warning/ObsoleteDTEXT.php',
'Egulias\\EmailValidator\\Warning\\QuotedPart' => $vendorDir . '/egulias/email-validator/src/Warning/QuotedPart.php',
'Egulias\\EmailValidator\\Warning\\QuotedString' => $vendorDir . '/egulias/email-validator/src/Warning/QuotedString.php',
'Egulias\\EmailValidator\\Warning\\TLD' => $vendorDir . '/egulias/email-validator/src/Warning/TLD.php',
'Egulias\\EmailValidator\\Warning\\Warning' => $vendorDir . '/egulias/email-validator/src/Warning/Warning.php',
'Filter\\FilterException' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/Filter/FilterException.php',
'Filter\\FilterFailedException' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/Filter/FilterFailedException.php',
'GuzzleHttp\\Psr7\\AppendStream' => $vendorDir . '/guzzlehttp/psr7/src/AppendStream.php',
'GuzzleHttp\\Psr7\\BufferStream' => $vendorDir . '/guzzlehttp/psr7/src/BufferStream.php',
'GuzzleHttp\\Psr7\\CachingStream' => $vendorDir . '/guzzlehttp/psr7/src/CachingStream.php',
'GuzzleHttp\\Psr7\\DroppingStream' => $vendorDir . '/guzzlehttp/psr7/src/DroppingStream.php',
'GuzzleHttp\\Psr7\\Exception\\MalformedUriException' => $vendorDir . '/guzzlehttp/psr7/src/Exception/MalformedUriException.php',
'GuzzleHttp\\Psr7\\FnStream' => $vendorDir . '/guzzlehttp/psr7/src/FnStream.php',
'GuzzleHttp\\Psr7\\Header' => $vendorDir . '/guzzlehttp/psr7/src/Header.php',
'GuzzleHttp\\Psr7\\HttpFactory' => $vendorDir . '/guzzlehttp/psr7/src/HttpFactory.php',
'GuzzleHttp\\Psr7\\InflateStream' => $vendorDir . '/guzzlehttp/psr7/src/InflateStream.php',
'GuzzleHttp\\Psr7\\LazyOpenStream' => $vendorDir . '/guzzlehttp/psr7/src/LazyOpenStream.php',
'GuzzleHttp\\Psr7\\LimitStream' => $vendorDir . '/guzzlehttp/psr7/src/LimitStream.php',
'GuzzleHttp\\Psr7\\Message' => $vendorDir . '/guzzlehttp/psr7/src/Message.php',
'GuzzleHttp\\Psr7\\MessageTrait' => $vendorDir . '/guzzlehttp/psr7/src/MessageTrait.php',
'GuzzleHttp\\Psr7\\MimeType' => $vendorDir . '/guzzlehttp/psr7/src/MimeType.php',
'GuzzleHttp\\Psr7\\MultipartStream' => $vendorDir . '/guzzlehttp/psr7/src/MultipartStream.php',
'GuzzleHttp\\Psr7\\NoSeekStream' => $vendorDir . '/guzzlehttp/psr7/src/NoSeekStream.php',
'GuzzleHttp\\Psr7\\PumpStream' => $vendorDir . '/guzzlehttp/psr7/src/PumpStream.php',
'GuzzleHttp\\Psr7\\Query' => $vendorDir . '/guzzlehttp/psr7/src/Query.php',
'GuzzleHttp\\Psr7\\Request' => $vendorDir . '/guzzlehttp/psr7/src/Request.php',
'GuzzleHttp\\Psr7\\Response' => $vendorDir . '/guzzlehttp/psr7/src/Response.php',
'GuzzleHttp\\Psr7\\Rfc3986' => $vendorDir . '/guzzlehttp/psr7/src/Rfc3986.php',
'GuzzleHttp\\Psr7\\Rfc7230' => $vendorDir . '/guzzlehttp/psr7/src/Rfc7230.php',
'GuzzleHttp\\Psr7\\ServerRequest' => $vendorDir . '/guzzlehttp/psr7/src/ServerRequest.php',
'GuzzleHttp\\Psr7\\Stream' => $vendorDir . '/guzzlehttp/psr7/src/Stream.php',
'GuzzleHttp\\Psr7\\StreamDecoratorTrait' => $vendorDir . '/guzzlehttp/psr7/src/StreamDecoratorTrait.php',
'GuzzleHttp\\Psr7\\StreamWrapper' => $vendorDir . '/guzzlehttp/psr7/src/StreamWrapper.php',
'GuzzleHttp\\Psr7\\UploadedFile' => $vendorDir . '/guzzlehttp/psr7/src/UploadedFile.php',
'GuzzleHttp\\Psr7\\Uri' => $vendorDir . '/guzzlehttp/psr7/src/Uri.php',
'GuzzleHttp\\Psr7\\UriComparator' => $vendorDir . '/guzzlehttp/psr7/src/UriComparator.php',
'GuzzleHttp\\Psr7\\UriNormalizer' => $vendorDir . '/guzzlehttp/psr7/src/UriNormalizer.php',
'GuzzleHttp\\Psr7\\UriResolver' => $vendorDir . '/guzzlehttp/psr7/src/UriResolver.php',
'GuzzleHttp\\Psr7\\Utils' => $vendorDir . '/guzzlehttp/psr7/src/Utils.php',
'Illuminate\\Contracts\\Auth\\Access\\Authorizable' => $vendorDir . '/illuminate/contracts/Auth/Access/Authorizable.php',
'Illuminate\\Contracts\\Auth\\Access\\Gate' => $vendorDir . '/illuminate/contracts/Auth/Access/Gate.php',
'Illuminate\\Contracts\\Auth\\Authenticatable' => $vendorDir . '/illuminate/contracts/Auth/Authenticatable.php',
'Illuminate\\Contracts\\Auth\\CanResetPassword' => $vendorDir . '/illuminate/contracts/Auth/CanResetPassword.php',
'Illuminate\\Contracts\\Auth\\Factory' => $vendorDir . '/illuminate/contracts/Auth/Factory.php',
'Illuminate\\Contracts\\Auth\\Guard' => $vendorDir . '/illuminate/contracts/Auth/Guard.php',
'Illuminate\\Contracts\\Auth\\Middleware\\AuthenticatesRequests' => $vendorDir . '/illuminate/contracts/Auth/Middleware/AuthenticatesRequests.php',
'Illuminate\\Contracts\\Auth\\MustVerifyEmail' => $vendorDir . '/illuminate/contracts/Auth/MustVerifyEmail.php',
'Illuminate\\Contracts\\Auth\\PasswordBroker' => $vendorDir . '/illuminate/contracts/Auth/PasswordBroker.php',
'Illuminate\\Contracts\\Auth\\PasswordBrokerFactory' => $vendorDir . '/illuminate/contracts/Auth/PasswordBrokerFactory.php',
'Illuminate\\Contracts\\Auth\\StatefulGuard' => $vendorDir . '/illuminate/contracts/Auth/StatefulGuard.php',
'Illuminate\\Contracts\\Auth\\SupportsBasicAuth' => $vendorDir . '/illuminate/contracts/Auth/SupportsBasicAuth.php',
'Illuminate\\Contracts\\Auth\\UserProvider' => $vendorDir . '/illuminate/contracts/Auth/UserProvider.php',
'Illuminate\\Contracts\\Broadcasting\\Broadcaster' => $vendorDir . '/illuminate/contracts/Broadcasting/Broadcaster.php',
'Illuminate\\Contracts\\Broadcasting\\Factory' => $vendorDir . '/illuminate/contracts/Broadcasting/Factory.php',
'Illuminate\\Contracts\\Broadcasting\\HasBroadcastChannel' => $vendorDir . '/illuminate/contracts/Broadcasting/HasBroadcastChannel.php',
'Illuminate\\Contracts\\Broadcasting\\ShouldBeUnique' => $vendorDir . '/illuminate/contracts/Broadcasting/ShouldBeUnique.php',
'Illuminate\\Contracts\\Broadcasting\\ShouldBroadcast' => $vendorDir . '/illuminate/contracts/Broadcasting/ShouldBroadcast.php',
'Illuminate\\Contracts\\Broadcasting\\ShouldBroadcastNow' => $vendorDir . '/illuminate/contracts/Broadcasting/ShouldBroadcastNow.php',
'Illuminate\\Contracts\\Broadcasting\\ShouldRescue' => $vendorDir . '/illuminate/contracts/Broadcasting/ShouldRescue.php',
'Illuminate\\Contracts\\Bus\\Dispatcher' => $vendorDir . '/illuminate/contracts/Bus/Dispatcher.php',
'Illuminate\\Contracts\\Bus\\QueueingDispatcher' => $vendorDir . '/illuminate/contracts/Bus/QueueingDispatcher.php',
'Illuminate\\Contracts\\Cache\\Factory' => $vendorDir . '/illuminate/contracts/Cache/Factory.php',
'Illuminate\\Contracts\\Cache\\Lock' => $vendorDir . '/illuminate/contracts/Cache/Lock.php',
'Illuminate\\Contracts\\Cache\\LockProvider' => $vendorDir . '/illuminate/contracts/Cache/LockProvider.php',
'Illuminate\\Contracts\\Cache\\LockTimeoutException' => $vendorDir . '/illuminate/contracts/Cache/LockTimeoutException.php',
'Illuminate\\Contracts\\Cache\\Repository' => $vendorDir . '/illuminate/contracts/Cache/Repository.php',
'Illuminate\\Contracts\\Cache\\Store' => $vendorDir . '/illuminate/contracts/Cache/Store.php',
'Illuminate\\Contracts\\Concurrency\\Driver' => $vendorDir . '/illuminate/contracts/Concurrency/Driver.php',
'Illuminate\\Contracts\\Config\\Repository' => $vendorDir . '/illuminate/contracts/Config/Repository.php',
'Illuminate\\Contracts\\Console\\Application' => $vendorDir . '/illuminate/contracts/Console/Application.php',
'Illuminate\\Contracts\\Console\\Isolatable' => $vendorDir . '/illuminate/contracts/Console/Isolatable.php',
'Illuminate\\Contracts\\Console\\Kernel' => $vendorDir . '/illuminate/contracts/Console/Kernel.php',
'Illuminate\\Contracts\\Console\\PromptsForMissingInput' => $vendorDir . '/illuminate/contracts/Console/PromptsForMissingInput.php',
'Illuminate\\Contracts\\Container\\BindingResolutionException' => $vendorDir . '/illuminate/contracts/Container/BindingResolutionException.php',
'Illuminate\\Contracts\\Container\\CircularDependencyException' => $vendorDir . '/illuminate/contracts/Container/CircularDependencyException.php',
'Illuminate\\Contracts\\Container\\Container' => $vendorDir . '/illuminate/contracts/Container/Container.php',
'Illuminate\\Contracts\\Container\\ContextualAttribute' => $vendorDir . '/illuminate/contracts/Container/ContextualAttribute.php',
'Illuminate\\Contracts\\Container\\ContextualBindingBuilder' => $vendorDir . '/illuminate/contracts/Container/ContextualBindingBuilder.php',
'Illuminate\\Contracts\\Container\\SelfBuilding' => $vendorDir . '/illuminate/contracts/Container/SelfBuilding.php',
'Illuminate\\Contracts\\Cookie\\Factory' => $vendorDir . '/illuminate/contracts/Cookie/Factory.php',
'Illuminate\\Contracts\\Cookie\\QueueingFactory' => $vendorDir . '/illuminate/contracts/Cookie/QueueingFactory.php',
'Illuminate\\Contracts\\Database\\ConcurrencyErrorDetector' => $vendorDir . '/illuminate/contracts/Database/ConcurrencyErrorDetector.php',
'Illuminate\\Contracts\\Database\\Eloquent\\Builder' => $vendorDir . '/illuminate/contracts/Database/Eloquent/Builder.php',
'Illuminate\\Contracts\\Database\\Eloquent\\Castable' => $vendorDir . '/illuminate/contracts/Database/Eloquent/Castable.php',
'Illuminate\\Contracts\\Database\\Eloquent\\CastsAttributes' => $vendorDir . '/illuminate/contracts/Database/Eloquent/CastsAttributes.php',
'Illuminate\\Contracts\\Database\\Eloquent\\CastsInboundAttributes' => $vendorDir . '/illuminate/contracts/Database/Eloquent/CastsInboundAttributes.php',
'Illuminate\\Contracts\\Database\\Eloquent\\ComparesCastableAttributes' => $vendorDir . '/illuminate/contracts/Database/Eloquent/ComparesCastableAttributes.php',
'Illuminate\\Contracts\\Database\\Eloquent\\DeviatesCastableAttributes' => $vendorDir . '/illuminate/contracts/Database/Eloquent/DeviatesCastableAttributes.php',
'Illuminate\\Contracts\\Database\\Eloquent\\SerializesCastableAttributes' => $vendorDir . '/illuminate/contracts/Database/Eloquent/SerializesCastableAttributes.php',
'Illuminate\\Contracts\\Database\\Eloquent\\SupportsPartialRelations' => $vendorDir . '/illuminate/contracts/Database/Eloquent/SupportsPartialRelations.php',
'Illuminate\\Contracts\\Database\\Events\\MigrationEvent' => $vendorDir . '/illuminate/contracts/Database/Events/MigrationEvent.php',
'Illuminate\\Contracts\\Database\\LostConnectionDetector' => $vendorDir . '/illuminate/contracts/Database/LostConnectionDetector.php',
'Illuminate\\Contracts\\Database\\ModelIdentifier' => $vendorDir . '/illuminate/contracts/Database/ModelIdentifier.php',
'Illuminate\\Contracts\\Database\\Query\\Builder' => $vendorDir . '/illuminate/contracts/Database/Query/Builder.php',
'Illuminate\\Contracts\\Database\\Query\\ConditionExpression' => $vendorDir . '/illuminate/contracts/Database/Query/ConditionExpression.php',
'Illuminate\\Contracts\\Database\\Query\\Expression' => $vendorDir . '/illuminate/contracts/Database/Query/Expression.php',
'Illuminate\\Contracts\\Debug\\ExceptionHandler' => $vendorDir . '/illuminate/contracts/Debug/ExceptionHandler.php',
'Illuminate\\Contracts\\Debug\\ShouldntReport' => $vendorDir . '/illuminate/contracts/Debug/ShouldntReport.php',
'Illuminate\\Contracts\\Encryption\\DecryptException' => $vendorDir . '/illuminate/contracts/Encryption/DecryptException.php',
'Illuminate\\Contracts\\Encryption\\EncryptException' => $vendorDir . '/illuminate/contracts/Encryption/EncryptException.php',
'Illuminate\\Contracts\\Encryption\\Encrypter' => $vendorDir . '/illuminate/contracts/Encryption/Encrypter.php',
'Illuminate\\Contracts\\Encryption\\StringEncrypter' => $vendorDir . '/illuminate/contracts/Encryption/StringEncrypter.php',
'Illuminate\\Contracts\\Events\\Dispatcher' => $vendorDir . '/illuminate/contracts/Events/Dispatcher.php',
'Illuminate\\Contracts\\Events\\ShouldDispatchAfterCommit' => $vendorDir . '/illuminate/contracts/Events/ShouldDispatchAfterCommit.php',
'Illuminate\\Contracts\\Events\\ShouldHandleEventsAfterCommit' => $vendorDir . '/illuminate/contracts/Events/ShouldHandleEventsAfterCommit.php',
'Illuminate\\Contracts\\Filesystem\\Cloud' => $vendorDir . '/illuminate/contracts/Filesystem/Cloud.php',
'Illuminate\\Contracts\\Filesystem\\Factory' => $vendorDir . '/illuminate/contracts/Filesystem/Factory.php',
'Illuminate\\Contracts\\Filesystem\\FileNotFoundException' => $vendorDir . '/illuminate/contracts/Filesystem/FileNotFoundException.php',
'Illuminate\\Contracts\\Filesystem\\Filesystem' => $vendorDir . '/illuminate/contracts/Filesystem/Filesystem.php',
'Illuminate\\Contracts\\Filesystem\\LockTimeoutException' => $vendorDir . '/illuminate/contracts/Filesystem/LockTimeoutException.php',
'Illuminate\\Contracts\\Foundation\\Application' => $vendorDir . '/illuminate/contracts/Foundation/Application.php',
'Illuminate\\Contracts\\Foundation\\CachesConfiguration' => $vendorDir . '/illuminate/contracts/Foundation/CachesConfiguration.php',
'Illuminate\\Contracts\\Foundation\\CachesRoutes' => $vendorDir . '/illuminate/contracts/Foundation/CachesRoutes.php',
'Illuminate\\Contracts\\Foundation\\ExceptionRenderer' => $vendorDir . '/illuminate/contracts/Foundation/ExceptionRenderer.php',
'Illuminate\\Contracts\\Foundation\\MaintenanceMode' => $vendorDir . '/illuminate/contracts/Foundation/MaintenanceMode.php',
'Illuminate\\Contracts\\Hashing\\Hasher' => $vendorDir . '/illuminate/contracts/Hashing/Hasher.php',
'Illuminate\\Contracts\\Http\\Kernel' => $vendorDir . '/illuminate/contracts/Http/Kernel.php',
'Illuminate\\Contracts\\JsonSchema\\JsonSchema' => $vendorDir . '/illuminate/contracts/JsonSchema/JsonSchema.php',
'Illuminate\\Contracts\\Log\\ContextLogProcessor' => $vendorDir . '/illuminate/contracts/Log/ContextLogProcessor.php',
'Illuminate\\Contracts\\Mail\\Attachable' => $vendorDir . '/illuminate/contracts/Mail/Attachable.php',
'Illuminate\\Contracts\\Mail\\Factory' => $vendorDir . '/illuminate/contracts/Mail/Factory.php',
'Illuminate\\Contracts\\Mail\\MailQueue' => $vendorDir . '/illuminate/contracts/Mail/MailQueue.php',
'Illuminate\\Contracts\\Mail\\Mailable' => $vendorDir . '/illuminate/contracts/Mail/Mailable.php',
'Illuminate\\Contracts\\Mail\\Mailer' => $vendorDir . '/illuminate/contracts/Mail/Mailer.php',
'Illuminate\\Contracts\\Notifications\\Dispatcher' => $vendorDir . '/illuminate/contracts/Notifications/Dispatcher.php',
'Illuminate\\Contracts\\Notifications\\Factory' => $vendorDir . '/illuminate/contracts/Notifications/Factory.php',
'Illuminate\\Contracts\\Pagination\\CursorPaginator' => $vendorDir . '/illuminate/contracts/Pagination/CursorPaginator.php',
'Illuminate\\Contracts\\Pagination\\LengthAwarePaginator' => $vendorDir . '/illuminate/contracts/Pagination/LengthAwarePaginator.php',
'Illuminate\\Contracts\\Pagination\\Paginator' => $vendorDir . '/illuminate/contracts/Pagination/Paginator.php',
'Illuminate\\Contracts\\Pipeline\\Hub' => $vendorDir . '/illuminate/contracts/Pipeline/Hub.php',
'Illuminate\\Contracts\\Pipeline\\Pipeline' => $vendorDir . '/illuminate/contracts/Pipeline/Pipeline.php',
'Illuminate\\Contracts\\Process\\InvokedProcess' => $vendorDir . '/illuminate/contracts/Process/InvokedProcess.php',
'Illuminate\\Contracts\\Process\\ProcessResult' => $vendorDir . '/illuminate/contracts/Process/ProcessResult.php',
'Illuminate\\Contracts\\Queue\\ClearableQueue' => $vendorDir . '/illuminate/contracts/Queue/ClearableQueue.php',
'Illuminate\\Contracts\\Queue\\EntityNotFoundException' => $vendorDir . '/illuminate/contracts/Queue/EntityNotFoundException.php',
'Illuminate\\Contracts\\Queue\\EntityResolver' => $vendorDir . '/illuminate/contracts/Queue/EntityResolver.php',
'Illuminate\\Contracts\\Queue\\Factory' => $vendorDir . '/illuminate/contracts/Queue/Factory.php',
'Illuminate\\Contracts\\Queue\\Job' => $vendorDir . '/illuminate/contracts/Queue/Job.php',
'Illuminate\\Contracts\\Queue\\Monitor' => $vendorDir . '/illuminate/contracts/Queue/Monitor.php',
'Illuminate\\Contracts\\Queue\\Queue' => $vendorDir . '/illuminate/contracts/Queue/Queue.php',
'Illuminate\\Contracts\\Queue\\QueueableCollection' => $vendorDir . '/illuminate/contracts/Queue/QueueableCollection.php',
'Illuminate\\Contracts\\Queue\\QueueableEntity' => $vendorDir . '/illuminate/contracts/Queue/QueueableEntity.php',
'Illuminate\\Contracts\\Queue\\ShouldBeEncrypted' => $vendorDir . '/illuminate/contracts/Queue/ShouldBeEncrypted.php',
'Illuminate\\Contracts\\Queue\\ShouldBeUnique' => $vendorDir . '/illuminate/contracts/Queue/ShouldBeUnique.php',
'Illuminate\\Contracts\\Queue\\ShouldBeUniqueUntilProcessing' => $vendorDir . '/illuminate/contracts/Queue/ShouldBeUniqueUntilProcessing.php',
'Illuminate\\Contracts\\Queue\\ShouldQueue' => $vendorDir . '/illuminate/contracts/Queue/ShouldQueue.php',
'Illuminate\\Contracts\\Queue\\ShouldQueueAfterCommit' => $vendorDir . '/illuminate/contracts/Queue/ShouldQueueAfterCommit.php',
'Illuminate\\Contracts\\Redis\\Connection' => $vendorDir . '/illuminate/contracts/Redis/Connection.php',
'Illuminate\\Contracts\\Redis\\Connector' => $vendorDir . '/illuminate/contracts/Redis/Connector.php',
'Illuminate\\Contracts\\Redis\\Factory' => $vendorDir . '/illuminate/contracts/Redis/Factory.php',
'Illuminate\\Contracts\\Redis\\LimiterTimeoutException' => $vendorDir . '/illuminate/contracts/Redis/LimiterTimeoutException.php',
'Illuminate\\Contracts\\Routing\\BindingRegistrar' => $vendorDir . '/illuminate/contracts/Routing/BindingRegistrar.php',
'Illuminate\\Contracts\\Routing\\Registrar' => $vendorDir . '/illuminate/contracts/Routing/Registrar.php',
'Illuminate\\Contracts\\Routing\\ResponseFactory' => $vendorDir . '/illuminate/contracts/Routing/ResponseFactory.php',
'Illuminate\\Contracts\\Routing\\UrlGenerator' => $vendorDir . '/illuminate/contracts/Routing/UrlGenerator.php',
'Illuminate\\Contracts\\Routing\\UrlRoutable' => $vendorDir . '/illuminate/contracts/Routing/UrlRoutable.php',
'Illuminate\\Contracts\\Session\\Middleware\\AuthenticatesSessions' => $vendorDir . '/illuminate/contracts/Session/Middleware/AuthenticatesSessions.php',
'Illuminate\\Contracts\\Session\\Session' => $vendorDir . '/illuminate/contracts/Session/Session.php',
'Illuminate\\Contracts\\Support\\Arrayable' => $vendorDir . '/illuminate/contracts/Support/Arrayable.php',
'Illuminate\\Contracts\\Support\\CanBeEscapedWhenCastToString' => $vendorDir . '/illuminate/contracts/Support/CanBeEscapedWhenCastToString.php',
'Illuminate\\Contracts\\Support\\DeferrableProvider' => $vendorDir . '/illuminate/contracts/Support/DeferrableProvider.php',
'Illuminate\\Contracts\\Support\\DeferringDisplayableValue' => $vendorDir . '/illuminate/contracts/Support/DeferringDisplayableValue.php',
'Illuminate\\Contracts\\Support\\HasOnceHash' => $vendorDir . '/illuminate/contracts/Support/HasOnceHash.php',
'Illuminate\\Contracts\\Support\\Htmlable' => $vendorDir . '/illuminate/contracts/Support/Htmlable.php',
'Illuminate\\Contracts\\Support\\Jsonable' => $vendorDir . '/illuminate/contracts/Support/Jsonable.php',
'Illuminate\\Contracts\\Support\\MessageBag' => $vendorDir . '/illuminate/contracts/Support/MessageBag.php',
'Illuminate\\Contracts\\Support\\MessageProvider' => $vendorDir . '/illuminate/contracts/Support/MessageProvider.php',
'Illuminate\\Contracts\\Support\\Renderable' => $vendorDir . '/illuminate/contracts/Support/Renderable.php',
'Illuminate\\Contracts\\Support\\Responsable' => $vendorDir . '/illuminate/contracts/Support/Responsable.php',
'Illuminate\\Contracts\\Support\\ValidatedData' => $vendorDir . '/illuminate/contracts/Support/ValidatedData.php',
'Illuminate\\Contracts\\Translation\\HasLocalePreference' => $vendorDir . '/illuminate/contracts/Translation/HasLocalePreference.php',
'Illuminate\\Contracts\\Translation\\Loader' => $vendorDir . '/illuminate/contracts/Translation/Loader.php',
'Illuminate\\Contracts\\Translation\\Translator' => $vendorDir . '/illuminate/contracts/Translation/Translator.php',
'Illuminate\\Contracts\\Validation\\CompilableRules' => $vendorDir . '/illuminate/contracts/Validation/CompilableRules.php',
'Illuminate\\Contracts\\Validation\\DataAwareRule' => $vendorDir . '/illuminate/contracts/Validation/DataAwareRule.php',
'Illuminate\\Contracts\\Validation\\Factory' => $vendorDir . '/illuminate/contracts/Validation/Factory.php',
'Illuminate\\Contracts\\Validation\\ImplicitRule' => $vendorDir . '/illuminate/contracts/Validation/ImplicitRule.php',
'Illuminate\\Contracts\\Validation\\InvokableRule' => $vendorDir . '/illuminate/contracts/Validation/InvokableRule.php',
'Illuminate\\Contracts\\Validation\\Rule' => $vendorDir . '/illuminate/contracts/Validation/Rule.php',
'Illuminate\\Contracts\\Validation\\UncompromisedVerifier' => $vendorDir . '/illuminate/contracts/Validation/UncompromisedVerifier.php',
'Illuminate\\Contracts\\Validation\\ValidatesWhenResolved' => $vendorDir . '/illuminate/contracts/Validation/ValidatesWhenResolved.php',
'Illuminate\\Contracts\\Validation\\ValidationRule' => $vendorDir . '/illuminate/contracts/Validation/ValidationRule.php',
'Illuminate\\Contracts\\Validation\\Validator' => $vendorDir . '/illuminate/contracts/Validation/Validator.php',
'Illuminate\\Contracts\\Validation\\ValidatorAwareRule' => $vendorDir . '/illuminate/contracts/Validation/ValidatorAwareRule.php',
'Illuminate\\Contracts\\View\\Engine' => $vendorDir . '/illuminate/contracts/View/Engine.php',
'Illuminate\\Contracts\\View\\Factory' => $vendorDir . '/illuminate/contracts/View/Factory.php',
'Illuminate\\Contracts\\View\\View' => $vendorDir . '/illuminate/contracts/View/View.php',
'Illuminate\\Contracts\\View\\ViewCompilationException' => $vendorDir . '/illuminate/contracts/View/ViewCompilationException.php',
'Illuminate\\Support\\Arr' => $vendorDir . '/illuminate/collections/Arr.php',
'Illuminate\\Support\\Collection' => $vendorDir . '/illuminate/collections/Collection.php',
'Illuminate\\Support\\Enumerable' => $vendorDir . '/illuminate/collections/Enumerable.php',
'Illuminate\\Support\\HigherOrderCollectionProxy' => $vendorDir . '/illuminate/collections/HigherOrderCollectionProxy.php',
'Illuminate\\Support\\HigherOrderWhenProxy' => $vendorDir . '/illuminate/conditionable/HigherOrderWhenProxy.php',
'Illuminate\\Support\\ItemNotFoundException' => $vendorDir . '/illuminate/collections/ItemNotFoundException.php',
'Illuminate\\Support\\LazyCollection' => $vendorDir . '/illuminate/collections/LazyCollection.php',
'Illuminate\\Support\\MultipleItemsFoundException' => $vendorDir . '/illuminate/collections/MultipleItemsFoundException.php',
'Illuminate\\Support\\Traits\\Conditionable' => $vendorDir . '/illuminate/conditionable/Traits/Conditionable.php',
'Illuminate\\Support\\Traits\\EnumeratesValues' => $vendorDir . '/illuminate/collections/Traits/EnumeratesValues.php',
'Illuminate\\Support\\Traits\\Macroable' => $vendorDir . '/illuminate/macroable/Traits/Macroable.php',
'Illuminate\\Support\\Traits\\TransformsToResourceCollection' => $vendorDir . '/illuminate/collections/Traits/TransformsToResourceCollection.php',
'Invoker\\CallableResolver' => $vendorDir . '/php-di/invoker/src/CallableResolver.php',
'Invoker\\Exception\\InvocationException' => $vendorDir . '/php-di/invoker/src/Exception/InvocationException.php',
'Invoker\\Exception\\NotCallableException' => $vendorDir . '/php-di/invoker/src/Exception/NotCallableException.php',
'Invoker\\Exception\\NotEnoughParametersException' => $vendorDir . '/php-di/invoker/src/Exception/NotEnoughParametersException.php',
'Invoker\\Invoker' => $vendorDir . '/php-di/invoker/src/Invoker.php',
'Invoker\\InvokerInterface' => $vendorDir . '/php-di/invoker/src/InvokerInterface.php',
'Invoker\\ParameterResolver\\AssociativeArrayResolver' => $vendorDir . '/php-di/invoker/src/ParameterResolver/AssociativeArrayResolver.php',
'Invoker\\ParameterResolver\\Container\\ParameterNameContainerResolver' => $vendorDir . '/php-di/invoker/src/ParameterResolver/Container/ParameterNameContainerResolver.php',
'Invoker\\ParameterResolver\\Container\\TypeHintContainerResolver' => $vendorDir . '/php-di/invoker/src/ParameterResolver/Container/TypeHintContainerResolver.php',
'Invoker\\ParameterResolver\\DefaultValueResolver' => $vendorDir . '/php-di/invoker/src/ParameterResolver/DefaultValueResolver.php',
'Invoker\\ParameterResolver\\NumericArrayResolver' => $vendorDir . '/php-di/invoker/src/ParameterResolver/NumericArrayResolver.php',
'Invoker\\ParameterResolver\\ParameterResolver' => $vendorDir . '/php-di/invoker/src/ParameterResolver/ParameterResolver.php',
'Invoker\\ParameterResolver\\ResolverChain' => $vendorDir . '/php-di/invoker/src/ParameterResolver/ResolverChain.php',
'Invoker\\ParameterResolver\\TypeHintResolver' => $vendorDir . '/php-di/invoker/src/ParameterResolver/TypeHintResolver.php',
'Invoker\\Reflection\\CallableReflection' => $vendorDir . '/php-di/invoker/src/Reflection/CallableReflection.php',
'Laravel\\SerializableClosure\\Contracts\\Serializable' => $vendorDir . '/laravel/serializable-closure/src/Contracts/Serializable.php',
'Laravel\\SerializableClosure\\Contracts\\Signer' => $vendorDir . '/laravel/serializable-closure/src/Contracts/Signer.php',
'Laravel\\SerializableClosure\\Exceptions\\InvalidSignatureException' => $vendorDir . '/laravel/serializable-closure/src/Exceptions/InvalidSignatureException.php',
'Laravel\\SerializableClosure\\Exceptions\\MissingSecretKeyException' => $vendorDir . '/laravel/serializable-closure/src/Exceptions/MissingSecretKeyException.php',
'Laravel\\SerializableClosure\\SerializableClosure' => $vendorDir . '/laravel/serializable-closure/src/SerializableClosure.php',
'Laravel\\SerializableClosure\\Serializers\\Native' => $vendorDir . '/laravel/serializable-closure/src/Serializers/Native.php',
'Laravel\\SerializableClosure\\Serializers\\Signed' => $vendorDir . '/laravel/serializable-closure/src/Serializers/Signed.php',
'Laravel\\SerializableClosure\\Signers\\Hmac' => $vendorDir . '/laravel/serializable-closure/src/Signers/Hmac.php',
'Laravel\\SerializableClosure\\Support\\ClosureScope' => $vendorDir . '/laravel/serializable-closure/src/Support/ClosureScope.php',
'Laravel\\SerializableClosure\\Support\\ClosureStream' => $vendorDir . '/laravel/serializable-closure/src/Support/ClosureStream.php',
'Laravel\\SerializableClosure\\Support\\ReflectionClosure' => $vendorDir . '/laravel/serializable-closure/src/Support/ReflectionClosure.php',
'Laravel\\SerializableClosure\\Support\\SelfReference' => $vendorDir . '/laravel/serializable-closure/src/Support/SelfReference.php',
'Laravel\\SerializableClosure\\UnsignedSerializableClosure' => $vendorDir . '/laravel/serializable-closure/src/UnsignedSerializableClosure.php',
'NoDiscard' => $vendorDir . '/symfony/polyfill-php85/Resources/stubs/NoDiscard.php',
'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
'Override' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/Override.php',
@@ -31,10 +591,356 @@ return array(
'Pdo\\Pgsql' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Pgsql.php',
'Pdo\\Sqlite' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/Pdo/Sqlite.php',
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'Psr\\Clock\\ClockInterface' => $vendorDir . '/psr/clock/src/ClockInterface.php',
'Psr\\Container\\ContainerExceptionInterface' => $vendorDir . '/psr/container/src/ContainerExceptionInterface.php',
'Psr\\Container\\ContainerInterface' => $vendorDir . '/psr/container/src/ContainerInterface.php',
'Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/psr/container/src/NotFoundExceptionInterface.php',
'Psr\\Http\\Message\\MessageInterface' => $vendorDir . '/psr/http-message/src/MessageInterface.php',
'Psr\\Http\\Message\\RequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/RequestFactoryInterface.php',
'Psr\\Http\\Message\\RequestInterface' => $vendorDir . '/psr/http-message/src/RequestInterface.php',
'Psr\\Http\\Message\\ResponseFactoryInterface' => $vendorDir . '/psr/http-factory/src/ResponseFactoryInterface.php',
'Psr\\Http\\Message\\ResponseInterface' => $vendorDir . '/psr/http-message/src/ResponseInterface.php',
'Psr\\Http\\Message\\ServerRequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/ServerRequestFactoryInterface.php',
'Psr\\Http\\Message\\ServerRequestInterface' => $vendorDir . '/psr/http-message/src/ServerRequestInterface.php',
'Psr\\Http\\Message\\StreamFactoryInterface' => $vendorDir . '/psr/http-factory/src/StreamFactoryInterface.php',
'Psr\\Http\\Message\\StreamInterface' => $vendorDir . '/psr/http-message/src/StreamInterface.php',
'Psr\\Http\\Message\\UploadedFileFactoryInterface' => $vendorDir . '/psr/http-factory/src/UploadedFileFactoryInterface.php',
'Psr\\Http\\Message\\UploadedFileInterface' => $vendorDir . '/psr/http-message/src/UploadedFileInterface.php',
'Psr\\Http\\Message\\UriFactoryInterface' => $vendorDir . '/psr/http-factory/src/UriFactoryInterface.php',
'Psr\\Http\\Message\\UriInterface' => $vendorDir . '/psr/http-message/src/UriInterface.php',
'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/src/AbstractLogger.php',
'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/src/InvalidArgumentException.php',
'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/src/LogLevel.php',
'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/src/LoggerAwareInterface.php',
'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/src/LoggerAwareTrait.php',
'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/src/LoggerInterface.php',
'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/src/LoggerTrait.php',
'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/src/NullLogger.php',
'Psr\\SimpleCache\\CacheException' => $vendorDir . '/psr/simple-cache/src/CacheException.php',
'Psr\\SimpleCache\\CacheInterface' => $vendorDir . '/psr/simple-cache/src/CacheInterface.php',
'Psr\\SimpleCache\\InvalidArgumentException' => $vendorDir . '/psr/simple-cache/src/InvalidArgumentException.php',
'ReflectionConstant' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/ReflectionConstant.php',
'RoundingMode' => $vendorDir . '/symfony/polyfill-php84/Resources/stubs/RoundingMode.php',
'SQLite3Exception' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php',
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'Symfony\\Component\\Clock\\Clock' => $vendorDir . '/symfony/clock/Clock.php',
'Symfony\\Component\\Clock\\ClockAwareTrait' => $vendorDir . '/symfony/clock/ClockAwareTrait.php',
'Symfony\\Component\\Clock\\ClockInterface' => $vendorDir . '/symfony/clock/ClockInterface.php',
'Symfony\\Component\\Clock\\DatePoint' => $vendorDir . '/symfony/clock/DatePoint.php',
'Symfony\\Component\\Clock\\MockClock' => $vendorDir . '/symfony/clock/MockClock.php',
'Symfony\\Component\\Clock\\MonotonicClock' => $vendorDir . '/symfony/clock/MonotonicClock.php',
'Symfony\\Component\\Clock\\NativeClock' => $vendorDir . '/symfony/clock/NativeClock.php',
'Symfony\\Component\\Clock\\Test\\ClockSensitiveTrait' => $vendorDir . '/symfony/clock/Test/ClockSensitiveTrait.php',
'Symfony\\Component\\Mime\\Address' => $vendorDir . '/symfony/mime/Address.php',
'Symfony\\Component\\Mime\\BodyRendererInterface' => $vendorDir . '/symfony/mime/BodyRendererInterface.php',
'Symfony\\Component\\Mime\\CharacterStream' => $vendorDir . '/symfony/mime/CharacterStream.php',
'Symfony\\Component\\Mime\\Crypto\\DkimOptions' => $vendorDir . '/symfony/mime/Crypto/DkimOptions.php',
'Symfony\\Component\\Mime\\Crypto\\DkimSigner' => $vendorDir . '/symfony/mime/Crypto/DkimSigner.php',
'Symfony\\Component\\Mime\\Crypto\\SMime' => $vendorDir . '/symfony/mime/Crypto/SMime.php',
'Symfony\\Component\\Mime\\Crypto\\SMimeEncrypter' => $vendorDir . '/symfony/mime/Crypto/SMimeEncrypter.php',
'Symfony\\Component\\Mime\\Crypto\\SMimeSigner' => $vendorDir . '/symfony/mime/Crypto/SMimeSigner.php',
'Symfony\\Component\\Mime\\DependencyInjection\\AddMimeTypeGuesserPass' => $vendorDir . '/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php',
'Symfony\\Component\\Mime\\DraftEmail' => $vendorDir . '/symfony/mime/DraftEmail.php',
'Symfony\\Component\\Mime\\Email' => $vendorDir . '/symfony/mime/Email.php',
'Symfony\\Component\\Mime\\Encoder\\AddressEncoderInterface' => $vendorDir . '/symfony/mime/Encoder/AddressEncoderInterface.php',
'Symfony\\Component\\Mime\\Encoder\\Base64ContentEncoder' => $vendorDir . '/symfony/mime/Encoder/Base64ContentEncoder.php',
'Symfony\\Component\\Mime\\Encoder\\Base64Encoder' => $vendorDir . '/symfony/mime/Encoder/Base64Encoder.php',
'Symfony\\Component\\Mime\\Encoder\\Base64MimeHeaderEncoder' => $vendorDir . '/symfony/mime/Encoder/Base64MimeHeaderEncoder.php',
'Symfony\\Component\\Mime\\Encoder\\ContentEncoderInterface' => $vendorDir . '/symfony/mime/Encoder/ContentEncoderInterface.php',
'Symfony\\Component\\Mime\\Encoder\\EightBitContentEncoder' => $vendorDir . '/symfony/mime/Encoder/EightBitContentEncoder.php',
'Symfony\\Component\\Mime\\Encoder\\EncoderInterface' => $vendorDir . '/symfony/mime/Encoder/EncoderInterface.php',
'Symfony\\Component\\Mime\\Encoder\\IdnAddressEncoder' => $vendorDir . '/symfony/mime/Encoder/IdnAddressEncoder.php',
'Symfony\\Component\\Mime\\Encoder\\MimeHeaderEncoderInterface' => $vendorDir . '/symfony/mime/Encoder/MimeHeaderEncoderInterface.php',
'Symfony\\Component\\Mime\\Encoder\\QpContentEncoder' => $vendorDir . '/symfony/mime/Encoder/QpContentEncoder.php',
'Symfony\\Component\\Mime\\Encoder\\QpEncoder' => $vendorDir . '/symfony/mime/Encoder/QpEncoder.php',
'Symfony\\Component\\Mime\\Encoder\\QpMimeHeaderEncoder' => $vendorDir . '/symfony/mime/Encoder/QpMimeHeaderEncoder.php',
'Symfony\\Component\\Mime\\Encoder\\Rfc2231Encoder' => $vendorDir . '/symfony/mime/Encoder/Rfc2231Encoder.php',
'Symfony\\Component\\Mime\\Exception\\AddressEncoderException' => $vendorDir . '/symfony/mime/Exception/AddressEncoderException.php',
'Symfony\\Component\\Mime\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/mime/Exception/ExceptionInterface.php',
'Symfony\\Component\\Mime\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/mime/Exception/InvalidArgumentException.php',
'Symfony\\Component\\Mime\\Exception\\LogicException' => $vendorDir . '/symfony/mime/Exception/LogicException.php',
'Symfony\\Component\\Mime\\Exception\\RfcComplianceException' => $vendorDir . '/symfony/mime/Exception/RfcComplianceException.php',
'Symfony\\Component\\Mime\\Exception\\RuntimeException' => $vendorDir . '/symfony/mime/Exception/RuntimeException.php',
'Symfony\\Component\\Mime\\FileBinaryMimeTypeGuesser' => $vendorDir . '/symfony/mime/FileBinaryMimeTypeGuesser.php',
'Symfony\\Component\\Mime\\FileinfoMimeTypeGuesser' => $vendorDir . '/symfony/mime/FileinfoMimeTypeGuesser.php',
'Symfony\\Component\\Mime\\Header\\AbstractHeader' => $vendorDir . '/symfony/mime/Header/AbstractHeader.php',
'Symfony\\Component\\Mime\\Header\\DateHeader' => $vendorDir . '/symfony/mime/Header/DateHeader.php',
'Symfony\\Component\\Mime\\Header\\HeaderInterface' => $vendorDir . '/symfony/mime/Header/HeaderInterface.php',
'Symfony\\Component\\Mime\\Header\\Headers' => $vendorDir . '/symfony/mime/Header/Headers.php',
'Symfony\\Component\\Mime\\Header\\IdentificationHeader' => $vendorDir . '/symfony/mime/Header/IdentificationHeader.php',
'Symfony\\Component\\Mime\\Header\\MailboxHeader' => $vendorDir . '/symfony/mime/Header/MailboxHeader.php',
'Symfony\\Component\\Mime\\Header\\MailboxListHeader' => $vendorDir . '/symfony/mime/Header/MailboxListHeader.php',
'Symfony\\Component\\Mime\\Header\\ParameterizedHeader' => $vendorDir . '/symfony/mime/Header/ParameterizedHeader.php',
'Symfony\\Component\\Mime\\Header\\PathHeader' => $vendorDir . '/symfony/mime/Header/PathHeader.php',
'Symfony\\Component\\Mime\\Header\\UnstructuredHeader' => $vendorDir . '/symfony/mime/Header/UnstructuredHeader.php',
'Symfony\\Component\\Mime\\HtmlToTextConverter\\DefaultHtmlToTextConverter' => $vendorDir . '/symfony/mime/HtmlToTextConverter/DefaultHtmlToTextConverter.php',
'Symfony\\Component\\Mime\\HtmlToTextConverter\\HtmlToTextConverterInterface' => $vendorDir . '/symfony/mime/HtmlToTextConverter/HtmlToTextConverterInterface.php',
'Symfony\\Component\\Mime\\HtmlToTextConverter\\LeagueHtmlToMarkdownConverter' => $vendorDir . '/symfony/mime/HtmlToTextConverter/LeagueHtmlToMarkdownConverter.php',
'Symfony\\Component\\Mime\\Message' => $vendorDir . '/symfony/mime/Message.php',
'Symfony\\Component\\Mime\\MessageConverter' => $vendorDir . '/symfony/mime/MessageConverter.php',
'Symfony\\Component\\Mime\\MimeTypeGuesserInterface' => $vendorDir . '/symfony/mime/MimeTypeGuesserInterface.php',
'Symfony\\Component\\Mime\\MimeTypes' => $vendorDir . '/symfony/mime/MimeTypes.php',
'Symfony\\Component\\Mime\\MimeTypesInterface' => $vendorDir . '/symfony/mime/MimeTypesInterface.php',
'Symfony\\Component\\Mime\\Part\\AbstractMultipartPart' => $vendorDir . '/symfony/mime/Part/AbstractMultipartPart.php',
'Symfony\\Component\\Mime\\Part\\AbstractPart' => $vendorDir . '/symfony/mime/Part/AbstractPart.php',
'Symfony\\Component\\Mime\\Part\\DataPart' => $vendorDir . '/symfony/mime/Part/DataPart.php',
'Symfony\\Component\\Mime\\Part\\File' => $vendorDir . '/symfony/mime/Part/File.php',
'Symfony\\Component\\Mime\\Part\\MessagePart' => $vendorDir . '/symfony/mime/Part/MessagePart.php',
'Symfony\\Component\\Mime\\Part\\Multipart\\AlternativePart' => $vendorDir . '/symfony/mime/Part/Multipart/AlternativePart.php',
'Symfony\\Component\\Mime\\Part\\Multipart\\DigestPart' => $vendorDir . '/symfony/mime/Part/Multipart/DigestPart.php',
'Symfony\\Component\\Mime\\Part\\Multipart\\FormDataPart' => $vendorDir . '/symfony/mime/Part/Multipart/FormDataPart.php',
'Symfony\\Component\\Mime\\Part\\Multipart\\MixedPart' => $vendorDir . '/symfony/mime/Part/Multipart/MixedPart.php',
'Symfony\\Component\\Mime\\Part\\Multipart\\RelatedPart' => $vendorDir . '/symfony/mime/Part/Multipart/RelatedPart.php',
'Symfony\\Component\\Mime\\Part\\SMimePart' => $vendorDir . '/symfony/mime/Part/SMimePart.php',
'Symfony\\Component\\Mime\\Part\\TextPart' => $vendorDir . '/symfony/mime/Part/TextPart.php',
'Symfony\\Component\\Mime\\RawMessage' => $vendorDir . '/symfony/mime/RawMessage.php',
'Symfony\\Component\\Mime\\Test\\Constraint\\EmailAddressContains' => $vendorDir . '/symfony/mime/Test/Constraint/EmailAddressContains.php',
'Symfony\\Component\\Mime\\Test\\Constraint\\EmailAttachmentCount' => $vendorDir . '/symfony/mime/Test/Constraint/EmailAttachmentCount.php',
'Symfony\\Component\\Mime\\Test\\Constraint\\EmailHasHeader' => $vendorDir . '/symfony/mime/Test/Constraint/EmailHasHeader.php',
'Symfony\\Component\\Mime\\Test\\Constraint\\EmailHeaderSame' => $vendorDir . '/symfony/mime/Test/Constraint/EmailHeaderSame.php',
'Symfony\\Component\\Mime\\Test\\Constraint\\EmailHtmlBodyContains' => $vendorDir . '/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php',
'Symfony\\Component\\Mime\\Test\\Constraint\\EmailSubjectContains' => $vendorDir . '/symfony/mime/Test/Constraint/EmailSubjectContains.php',
'Symfony\\Component\\Mime\\Test\\Constraint\\EmailTextBodyContains' => $vendorDir . '/symfony/mime/Test/Constraint/EmailTextBodyContains.php',
'Symfony\\Component\\Translation\\CatalogueMetadataAwareInterface' => $vendorDir . '/symfony/translation/CatalogueMetadataAwareInterface.php',
'Symfony\\Component\\Translation\\Catalogue\\AbstractOperation' => $vendorDir . '/symfony/translation/Catalogue/AbstractOperation.php',
'Symfony\\Component\\Translation\\Catalogue\\MergeOperation' => $vendorDir . '/symfony/translation/Catalogue/MergeOperation.php',
'Symfony\\Component\\Translation\\Catalogue\\OperationInterface' => $vendorDir . '/symfony/translation/Catalogue/OperationInterface.php',
'Symfony\\Component\\Translation\\Catalogue\\TargetOperation' => $vendorDir . '/symfony/translation/Catalogue/TargetOperation.php',
'Symfony\\Component\\Translation\\Command\\TranslationLintCommand' => $vendorDir . '/symfony/translation/Command/TranslationLintCommand.php',
'Symfony\\Component\\Translation\\Command\\TranslationPullCommand' => $vendorDir . '/symfony/translation/Command/TranslationPullCommand.php',
'Symfony\\Component\\Translation\\Command\\TranslationPushCommand' => $vendorDir . '/symfony/translation/Command/TranslationPushCommand.php',
'Symfony\\Component\\Translation\\Command\\TranslationTrait' => $vendorDir . '/symfony/translation/Command/TranslationTrait.php',
'Symfony\\Component\\Translation\\Command\\XliffLintCommand' => $vendorDir . '/symfony/translation/Command/XliffLintCommand.php',
'Symfony\\Component\\Translation\\DataCollectorTranslator' => $vendorDir . '/symfony/translation/DataCollectorTranslator.php',
'Symfony\\Component\\Translation\\DataCollector\\TranslationDataCollector' => $vendorDir . '/symfony/translation/DataCollector/TranslationDataCollector.php',
'Symfony\\Component\\Translation\\DependencyInjection\\DataCollectorTranslatorPass' => $vendorDir . '/symfony/translation/DependencyInjection/DataCollectorTranslatorPass.php',
'Symfony\\Component\\Translation\\DependencyInjection\\LoggingTranslatorPass' => $vendorDir . '/symfony/translation/DependencyInjection/LoggingTranslatorPass.php',
'Symfony\\Component\\Translation\\DependencyInjection\\TranslationDumperPass' => $vendorDir . '/symfony/translation/DependencyInjection/TranslationDumperPass.php',
'Symfony\\Component\\Translation\\DependencyInjection\\TranslationExtractorPass' => $vendorDir . '/symfony/translation/DependencyInjection/TranslationExtractorPass.php',
'Symfony\\Component\\Translation\\DependencyInjection\\TranslatorPass' => $vendorDir . '/symfony/translation/DependencyInjection/TranslatorPass.php',
'Symfony\\Component\\Translation\\DependencyInjection\\TranslatorPathsPass' => $vendorDir . '/symfony/translation/DependencyInjection/TranslatorPathsPass.php',
'Symfony\\Component\\Translation\\Dumper\\CsvFileDumper' => $vendorDir . '/symfony/translation/Dumper/CsvFileDumper.php',
'Symfony\\Component\\Translation\\Dumper\\DumperInterface' => $vendorDir . '/symfony/translation/Dumper/DumperInterface.php',
'Symfony\\Component\\Translation\\Dumper\\FileDumper' => $vendorDir . '/symfony/translation/Dumper/FileDumper.php',
'Symfony\\Component\\Translation\\Dumper\\IcuResFileDumper' => $vendorDir . '/symfony/translation/Dumper/IcuResFileDumper.php',
'Symfony\\Component\\Translation\\Dumper\\IniFileDumper' => $vendorDir . '/symfony/translation/Dumper/IniFileDumper.php',
'Symfony\\Component\\Translation\\Dumper\\JsonFileDumper' => $vendorDir . '/symfony/translation/Dumper/JsonFileDumper.php',
'Symfony\\Component\\Translation\\Dumper\\MoFileDumper' => $vendorDir . '/symfony/translation/Dumper/MoFileDumper.php',
'Symfony\\Component\\Translation\\Dumper\\PhpFileDumper' => $vendorDir . '/symfony/translation/Dumper/PhpFileDumper.php',
'Symfony\\Component\\Translation\\Dumper\\PoFileDumper' => $vendorDir . '/symfony/translation/Dumper/PoFileDumper.php',
'Symfony\\Component\\Translation\\Dumper\\QtFileDumper' => $vendorDir . '/symfony/translation/Dumper/QtFileDumper.php',
'Symfony\\Component\\Translation\\Dumper\\XliffFileDumper' => $vendorDir . '/symfony/translation/Dumper/XliffFileDumper.php',
'Symfony\\Component\\Translation\\Dumper\\YamlFileDumper' => $vendorDir . '/symfony/translation/Dumper/YamlFileDumper.php',
'Symfony\\Component\\Translation\\Exception\\ExceptionInterface' => $vendorDir . '/symfony/translation/Exception/ExceptionInterface.php',
'Symfony\\Component\\Translation\\Exception\\IncompleteDsnException' => $vendorDir . '/symfony/translation/Exception/IncompleteDsnException.php',
'Symfony\\Component\\Translation\\Exception\\InvalidArgumentException' => $vendorDir . '/symfony/translation/Exception/InvalidArgumentException.php',
'Symfony\\Component\\Translation\\Exception\\InvalidResourceException' => $vendorDir . '/symfony/translation/Exception/InvalidResourceException.php',
'Symfony\\Component\\Translation\\Exception\\LogicException' => $vendorDir . '/symfony/translation/Exception/LogicException.php',
'Symfony\\Component\\Translation\\Exception\\MissingRequiredOptionException' => $vendorDir . '/symfony/translation/Exception/MissingRequiredOptionException.php',
'Symfony\\Component\\Translation\\Exception\\NotFoundResourceException' => $vendorDir . '/symfony/translation/Exception/NotFoundResourceException.php',
'Symfony\\Component\\Translation\\Exception\\ProviderException' => $vendorDir . '/symfony/translation/Exception/ProviderException.php',
'Symfony\\Component\\Translation\\Exception\\ProviderExceptionInterface' => $vendorDir . '/symfony/translation/Exception/ProviderExceptionInterface.php',
'Symfony\\Component\\Translation\\Exception\\RuntimeException' => $vendorDir . '/symfony/translation/Exception/RuntimeException.php',
'Symfony\\Component\\Translation\\Exception\\UnsupportedSchemeException' => $vendorDir . '/symfony/translation/Exception/UnsupportedSchemeException.php',
'Symfony\\Component\\Translation\\Extractor\\AbstractFileExtractor' => $vendorDir . '/symfony/translation/Extractor/AbstractFileExtractor.php',
'Symfony\\Component\\Translation\\Extractor\\ChainExtractor' => $vendorDir . '/symfony/translation/Extractor/ChainExtractor.php',
'Symfony\\Component\\Translation\\Extractor\\ExtractorInterface' => $vendorDir . '/symfony/translation/Extractor/ExtractorInterface.php',
'Symfony\\Component\\Translation\\Extractor\\PhpAstExtractor' => $vendorDir . '/symfony/translation/Extractor/PhpAstExtractor.php',
'Symfony\\Component\\Translation\\Extractor\\Visitor\\AbstractVisitor' => $vendorDir . '/symfony/translation/Extractor/Visitor/AbstractVisitor.php',
'Symfony\\Component\\Translation\\Extractor\\Visitor\\ConstraintVisitor' => $vendorDir . '/symfony/translation/Extractor/Visitor/ConstraintVisitor.php',
'Symfony\\Component\\Translation\\Extractor\\Visitor\\TransMethodVisitor' => $vendorDir . '/symfony/translation/Extractor/Visitor/TransMethodVisitor.php',
'Symfony\\Component\\Translation\\Extractor\\Visitor\\TranslatableMessageVisitor' => $vendorDir . '/symfony/translation/Extractor/Visitor/TranslatableMessageVisitor.php',
'Symfony\\Component\\Translation\\Formatter\\IntlFormatter' => $vendorDir . '/symfony/translation/Formatter/IntlFormatter.php',
'Symfony\\Component\\Translation\\Formatter\\IntlFormatterInterface' => $vendorDir . '/symfony/translation/Formatter/IntlFormatterInterface.php',
'Symfony\\Component\\Translation\\Formatter\\MessageFormatter' => $vendorDir . '/symfony/translation/Formatter/MessageFormatter.php',
'Symfony\\Component\\Translation\\Formatter\\MessageFormatterInterface' => $vendorDir . '/symfony/translation/Formatter/MessageFormatterInterface.php',
'Symfony\\Component\\Translation\\IdentityTranslator' => $vendorDir . '/symfony/translation/IdentityTranslator.php',
'Symfony\\Component\\Translation\\Loader\\ArrayLoader' => $vendorDir . '/symfony/translation/Loader/ArrayLoader.php',
'Symfony\\Component\\Translation\\Loader\\CsvFileLoader' => $vendorDir . '/symfony/translation/Loader/CsvFileLoader.php',
'Symfony\\Component\\Translation\\Loader\\FileLoader' => $vendorDir . '/symfony/translation/Loader/FileLoader.php',
'Symfony\\Component\\Translation\\Loader\\IcuDatFileLoader' => $vendorDir . '/symfony/translation/Loader/IcuDatFileLoader.php',
'Symfony\\Component\\Translation\\Loader\\IcuResFileLoader' => $vendorDir . '/symfony/translation/Loader/IcuResFileLoader.php',
'Symfony\\Component\\Translation\\Loader\\IniFileLoader' => $vendorDir . '/symfony/translation/Loader/IniFileLoader.php',
'Symfony\\Component\\Translation\\Loader\\JsonFileLoader' => $vendorDir . '/symfony/translation/Loader/JsonFileLoader.php',
'Symfony\\Component\\Translation\\Loader\\LoaderInterface' => $vendorDir . '/symfony/translation/Loader/LoaderInterface.php',
'Symfony\\Component\\Translation\\Loader\\MoFileLoader' => $vendorDir . '/symfony/translation/Loader/MoFileLoader.php',
'Symfony\\Component\\Translation\\Loader\\PhpFileLoader' => $vendorDir . '/symfony/translation/Loader/PhpFileLoader.php',
'Symfony\\Component\\Translation\\Loader\\PoFileLoader' => $vendorDir . '/symfony/translation/Loader/PoFileLoader.php',
'Symfony\\Component\\Translation\\Loader\\QtFileLoader' => $vendorDir . '/symfony/translation/Loader/QtFileLoader.php',
'Symfony\\Component\\Translation\\Loader\\XliffFileLoader' => $vendorDir . '/symfony/translation/Loader/XliffFileLoader.php',
'Symfony\\Component\\Translation\\Loader\\YamlFileLoader' => $vendorDir . '/symfony/translation/Loader/YamlFileLoader.php',
'Symfony\\Component\\Translation\\LocaleSwitcher' => $vendorDir . '/symfony/translation/LocaleSwitcher.php',
'Symfony\\Component\\Translation\\LoggingTranslator' => $vendorDir . '/symfony/translation/LoggingTranslator.php',
'Symfony\\Component\\Translation\\MessageCatalogue' => $vendorDir . '/symfony/translation/MessageCatalogue.php',
'Symfony\\Component\\Translation\\MessageCatalogueInterface' => $vendorDir . '/symfony/translation/MessageCatalogueInterface.php',
'Symfony\\Component\\Translation\\MetadataAwareInterface' => $vendorDir . '/symfony/translation/MetadataAwareInterface.php',
'Symfony\\Component\\Translation\\Provider\\AbstractProviderFactory' => $vendorDir . '/symfony/translation/Provider/AbstractProviderFactory.php',
'Symfony\\Component\\Translation\\Provider\\Dsn' => $vendorDir . '/symfony/translation/Provider/Dsn.php',
'Symfony\\Component\\Translation\\Provider\\FilteringProvider' => $vendorDir . '/symfony/translation/Provider/FilteringProvider.php',
'Symfony\\Component\\Translation\\Provider\\NullProvider' => $vendorDir . '/symfony/translation/Provider/NullProvider.php',
'Symfony\\Component\\Translation\\Provider\\NullProviderFactory' => $vendorDir . '/symfony/translation/Provider/NullProviderFactory.php',
'Symfony\\Component\\Translation\\Provider\\ProviderFactoryInterface' => $vendorDir . '/symfony/translation/Provider/ProviderFactoryInterface.php',
'Symfony\\Component\\Translation\\Provider\\ProviderInterface' => $vendorDir . '/symfony/translation/Provider/ProviderInterface.php',
'Symfony\\Component\\Translation\\Provider\\TranslationProviderCollection' => $vendorDir . '/symfony/translation/Provider/TranslationProviderCollection.php',
'Symfony\\Component\\Translation\\Provider\\TranslationProviderCollectionFactory' => $vendorDir . '/symfony/translation/Provider/TranslationProviderCollectionFactory.php',
'Symfony\\Component\\Translation\\PseudoLocalizationTranslator' => $vendorDir . '/symfony/translation/PseudoLocalizationTranslator.php',
'Symfony\\Component\\Translation\\Reader\\TranslationReader' => $vendorDir . '/symfony/translation/Reader/TranslationReader.php',
'Symfony\\Component\\Translation\\Reader\\TranslationReaderInterface' => $vendorDir . '/symfony/translation/Reader/TranslationReaderInterface.php',
'Symfony\\Component\\Translation\\StaticMessage' => $vendorDir . '/symfony/translation/StaticMessage.php',
'Symfony\\Component\\Translation\\Test\\AbstractProviderFactoryTestCase' => $vendorDir . '/symfony/translation/Test/AbstractProviderFactoryTestCase.php',
'Symfony\\Component\\Translation\\Test\\IncompleteDsnTestTrait' => $vendorDir . '/symfony/translation/Test/IncompleteDsnTestTrait.php',
'Symfony\\Component\\Translation\\Test\\ProviderFactoryTestCase' => $vendorDir . '/symfony/translation/Test/ProviderFactoryTestCase.php',
'Symfony\\Component\\Translation\\Test\\ProviderTestCase' => $vendorDir . '/symfony/translation/Test/ProviderTestCase.php',
'Symfony\\Component\\Translation\\TranslatableMessage' => $vendorDir . '/symfony/translation/TranslatableMessage.php',
'Symfony\\Component\\Translation\\Translator' => $vendorDir . '/symfony/translation/Translator.php',
'Symfony\\Component\\Translation\\TranslatorBag' => $vendorDir . '/symfony/translation/TranslatorBag.php',
'Symfony\\Component\\Translation\\TranslatorBagInterface' => $vendorDir . '/symfony/translation/TranslatorBagInterface.php',
'Symfony\\Component\\Translation\\Util\\ArrayConverter' => $vendorDir . '/symfony/translation/Util/ArrayConverter.php',
'Symfony\\Component\\Translation\\Util\\XliffUtils' => $vendorDir . '/symfony/translation/Util/XliffUtils.php',
'Symfony\\Component\\Translation\\Writer\\TranslationWriter' => $vendorDir . '/symfony/translation/Writer/TranslationWriter.php',
'Symfony\\Component\\Translation\\Writer\\TranslationWriterInterface' => $vendorDir . '/symfony/translation/Writer/TranslationWriterInterface.php',
'Symfony\\Contracts\\Translation\\LocaleAwareInterface' => $vendorDir . '/symfony/translation-contracts/LocaleAwareInterface.php',
'Symfony\\Contracts\\Translation\\TranslatableInterface' => $vendorDir . '/symfony/translation-contracts/TranslatableInterface.php',
'Symfony\\Contracts\\Translation\\TranslatorInterface' => $vendorDir . '/symfony/translation-contracts/TranslatorInterface.php',
'Symfony\\Contracts\\Translation\\TranslatorTrait' => $vendorDir . '/symfony/translation-contracts/TranslatorTrait.php',
'Symfony\\Polyfill\\Iconv\\Iconv' => $vendorDir . '/symfony/polyfill-iconv/Iconv.php',
'Symfony\\Polyfill\\Intl\\Idn\\Idn' => $vendorDir . '/symfony/polyfill-intl-idn/Idn.php',
'Symfony\\Polyfill\\Intl\\Idn\\Info' => $vendorDir . '/symfony/polyfill-intl-idn/Info.php',
'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\DisallowedRanges' => $vendorDir . '/symfony/polyfill-intl-idn/Resources/unidata/DisallowedRanges.php',
'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\Regex' => $vendorDir . '/symfony/polyfill-intl-idn/Resources/unidata/Regex.php',
'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php',
'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php',
'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php',
'Symfony\\Polyfill\\Php80\\PhpToken' => $vendorDir . '/symfony/polyfill-php80/PhpToken.php',
'Symfony\\Polyfill\\Php83\\Php83' => $vendorDir . '/symfony/polyfill-php83/Php83.php',
'Symfony\\Polyfill\\Php84\\Php84' => $vendorDir . '/symfony/polyfill-php84/Php84.php',
'Symfony\\Polyfill\\Php85\\Php85' => $vendorDir . '/symfony/polyfill-php85/Php85.php',
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'ZBateson\\MailMimeParser\\Error' => $vendorDir . '/zbateson/mail-mime-parser/src/Error.php',
'ZBateson\\MailMimeParser\\ErrorBag' => $vendorDir . '/zbateson/mail-mime-parser/src/ErrorBag.php',
'ZBateson\\MailMimeParser\\Header\\AbstractHeader' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/AbstractHeader.php',
'ZBateson\\MailMimeParser\\Header\\AddressHeader' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/AddressHeader.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\AbstractConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/AbstractConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\AbstractGenericConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/AbstractGenericConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\AddressBaseConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/AddressBaseConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\AddressConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/AddressConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\AddressEmailConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/AddressEmailConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\AddressGroupConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/AddressGroupConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\CommentConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/CommentConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\DateConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/DateConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\GenericConsumerMimeLiteralPartService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/GenericConsumerMimeLiteralPartService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\GenericConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/GenericConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\IConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/IConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\IdBaseConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/IdBaseConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\IdConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/IdConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\ParameterConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/ParameterConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\ParameterNameValueConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/ParameterNameValueConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\ParameterValueConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/ParameterValueConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\QuotedStringConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/QuotedStringConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\QuotedStringMimeLiteralPartConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/QuotedStringMimeLiteralPartConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\QuotedStringMimeLiteralPartTokenSplitPatternTrait' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/QuotedStringMimeLiteralPartTokenSplitPatternTrait.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\ReceivedConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/ReceivedConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\Received\\DomainConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/Received/DomainConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\Received\\GenericReceivedConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/Received/GenericReceivedConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\Received\\ReceivedDateConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/Received/ReceivedDateConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\Consumer\\SubjectConsumerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Consumer/SubjectConsumerService.php',
'ZBateson\\MailMimeParser\\Header\\DateHeader' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/DateHeader.php',
'ZBateson\\MailMimeParser\\Header\\GenericHeader' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/GenericHeader.php',
'ZBateson\\MailMimeParser\\Header\\HeaderConsts' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/HeaderConsts.php',
'ZBateson\\MailMimeParser\\Header\\HeaderFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/HeaderFactory.php',
'ZBateson\\MailMimeParser\\Header\\IHeader' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/IHeader.php',
'ZBateson\\MailMimeParser\\Header\\IHeaderPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/IHeaderPart.php',
'ZBateson\\MailMimeParser\\Header\\IdHeader' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/IdHeader.php',
'ZBateson\\MailMimeParser\\Header\\MimeEncodedHeader' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/MimeEncodedHeader.php',
'ZBateson\\MailMimeParser\\Header\\ParameterHeader' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/ParameterHeader.php',
'ZBateson\\MailMimeParser\\Header\\Part\\AddressGroupPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/AddressGroupPart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\AddressPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/AddressPart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\CommentPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/CommentPart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\ContainerPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/ContainerPart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\DatePart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/DatePart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\HeaderPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/HeaderPart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\HeaderPartFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/HeaderPartFactory.php',
'ZBateson\\MailMimeParser\\Header\\Part\\MimeToken' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/MimeToken.php',
'ZBateson\\MailMimeParser\\Header\\Part\\MimeTokenPartFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/MimeTokenPartFactory.php',
'ZBateson\\MailMimeParser\\Header\\Part\\NameValuePart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/NameValuePart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\ParameterPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/ParameterPart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\QuotedLiteralPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/QuotedLiteralPart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\ReceivedDomainPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/ReceivedDomainPart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\ReceivedPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/ReceivedPart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\SplitParameterPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/SplitParameterPart.php',
'ZBateson\\MailMimeParser\\Header\\Part\\SubjectToken' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/SubjectToken.php',
'ZBateson\\MailMimeParser\\Header\\Part\\Token' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/Part/Token.php',
'ZBateson\\MailMimeParser\\Header\\ReceivedHeader' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/ReceivedHeader.php',
'ZBateson\\MailMimeParser\\Header\\SubjectHeader' => $vendorDir . '/zbateson/mail-mime-parser/src/Header/SubjectHeader.php',
'ZBateson\\MailMimeParser\\IErrorBag' => $vendorDir . '/zbateson/mail-mime-parser/src/IErrorBag.php',
'ZBateson\\MailMimeParser\\IMessage' => $vendorDir . '/zbateson/mail-mime-parser/src/IMessage.php',
'ZBateson\\MailMimeParser\\MailMimeParser' => $vendorDir . '/zbateson/mail-mime-parser/src/MailMimeParser.php',
'ZBateson\\MailMimeParser\\Message' => $vendorDir . '/zbateson/mail-mime-parser/src/Message.php',
'ZBateson\\MailMimeParser\\Message\\Factory\\IMessagePartFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/Factory/IMessagePartFactory.php',
'ZBateson\\MailMimeParser\\Message\\Factory\\IMimePartFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/Factory/IMimePartFactory.php',
'ZBateson\\MailMimeParser\\Message\\Factory\\IUUEncodedPartFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/Factory/IUUEncodedPartFactory.php',
'ZBateson\\MailMimeParser\\Message\\Factory\\PartChildrenContainerFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/Factory/PartChildrenContainerFactory.php',
'ZBateson\\MailMimeParser\\Message\\Factory\\PartHeaderContainerFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/Factory/PartHeaderContainerFactory.php',
'ZBateson\\MailMimeParser\\Message\\Factory\\PartStreamContainerFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/Factory/PartStreamContainerFactory.php',
'ZBateson\\MailMimeParser\\Message\\Helper\\AbstractHelper' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/Helper/AbstractHelper.php',
'ZBateson\\MailMimeParser\\Message\\Helper\\GenericHelper' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/Helper/GenericHelper.php',
'ZBateson\\MailMimeParser\\Message\\Helper\\MultipartHelper' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/Helper/MultipartHelper.php',
'ZBateson\\MailMimeParser\\Message\\Helper\\PrivacyHelper' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/Helper/PrivacyHelper.php',
'ZBateson\\MailMimeParser\\Message\\IMessagePart' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/IMessagePart.php',
'ZBateson\\MailMimeParser\\Message\\IMimePart' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/IMimePart.php',
'ZBateson\\MailMimeParser\\Message\\IMultiPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/IMultiPart.php',
'ZBateson\\MailMimeParser\\Message\\IUUEncodedPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/IUUEncodedPart.php',
'ZBateson\\MailMimeParser\\Message\\MessagePart' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/MessagePart.php',
'ZBateson\\MailMimeParser\\Message\\MimePart' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/MimePart.php',
'ZBateson\\MailMimeParser\\Message\\MultiPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/MultiPart.php',
'ZBateson\\MailMimeParser\\Message\\NonMimePart' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/NonMimePart.php',
'ZBateson\\MailMimeParser\\Message\\PartChildrenContainer' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/PartChildrenContainer.php',
'ZBateson\\MailMimeParser\\Message\\PartFilter' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/PartFilter.php',
'ZBateson\\MailMimeParser\\Message\\PartHeaderContainer' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/PartHeaderContainer.php',
'ZBateson\\MailMimeParser\\Message\\PartStreamContainer' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/PartStreamContainer.php',
'ZBateson\\MailMimeParser\\Message\\UUEncodedPart' => $vendorDir . '/zbateson/mail-mime-parser/src/Message/UUEncodedPart.php',
'ZBateson\\MailMimeParser\\Parser\\AbstractParserService' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/AbstractParserService.php',
'ZBateson\\MailMimeParser\\Parser\\CompatibleParserNotFoundException' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/CompatibleParserNotFoundException.php',
'ZBateson\\MailMimeParser\\Parser\\HeaderParserService' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/HeaderParserService.php',
'ZBateson\\MailMimeParser\\Parser\\IParserService' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/IParserService.php',
'ZBateson\\MailMimeParser\\Parser\\MessageParserService' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/MessageParserService.php',
'ZBateson\\MailMimeParser\\Parser\\MimeParserService' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/MimeParserService.php',
'ZBateson\\MailMimeParser\\Parser\\NonMimeParserService' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/NonMimeParserService.php',
'ZBateson\\MailMimeParser\\Parser\\ParserManagerService' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/ParserManagerService.php',
'ZBateson\\MailMimeParser\\Parser\\PartBuilder' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/PartBuilder.php',
'ZBateson\\MailMimeParser\\Parser\\PartBuilderFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/PartBuilderFactory.php',
'ZBateson\\MailMimeParser\\Parser\\Part\\ParserPartChildrenContainer' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Part/ParserPartChildrenContainer.php',
'ZBateson\\MailMimeParser\\Parser\\Part\\ParserPartChildrenContainerFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Part/ParserPartChildrenContainerFactory.php',
'ZBateson\\MailMimeParser\\Parser\\Part\\ParserPartStreamContainer' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Part/ParserPartStreamContainer.php',
'ZBateson\\MailMimeParser\\Parser\\Part\\ParserPartStreamContainerFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Part/ParserPartStreamContainerFactory.php',
'ZBateson\\MailMimeParser\\Parser\\Part\\UUEncodedPartHeaderContainer' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Part/UUEncodedPartHeaderContainer.php',
'ZBateson\\MailMimeParser\\Parser\\Part\\UUEncodedPartHeaderContainerFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Part/UUEncodedPartHeaderContainerFactory.php',
'ZBateson\\MailMimeParser\\Parser\\Proxy\\ParserMessageProxy' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Proxy/ParserMessageProxy.php',
'ZBateson\\MailMimeParser\\Parser\\Proxy\\ParserMessageProxyFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Proxy/ParserMessageProxyFactory.php',
'ZBateson\\MailMimeParser\\Parser\\Proxy\\ParserMimePartProxy' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Proxy/ParserMimePartProxy.php',
'ZBateson\\MailMimeParser\\Parser\\Proxy\\ParserMimePartProxyFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Proxy/ParserMimePartProxyFactory.php',
'ZBateson\\MailMimeParser\\Parser\\Proxy\\ParserNonMimeMessageProxy' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Proxy/ParserNonMimeMessageProxy.php',
'ZBateson\\MailMimeParser\\Parser\\Proxy\\ParserNonMimeMessageProxyFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Proxy/ParserNonMimeMessageProxyFactory.php',
'ZBateson\\MailMimeParser\\Parser\\Proxy\\ParserPartProxy' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Proxy/ParserPartProxy.php',
'ZBateson\\MailMimeParser\\Parser\\Proxy\\ParserPartProxyFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Proxy/ParserPartProxyFactory.php',
'ZBateson\\MailMimeParser\\Parser\\Proxy\\ParserUUEncodedPartProxy' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Proxy/ParserUUEncodedPartProxy.php',
'ZBateson\\MailMimeParser\\Parser\\Proxy\\ParserUUEncodedPartProxyFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Parser/Proxy/ParserUUEncodedPartProxyFactory.php',
'ZBateson\\MailMimeParser\\Stream\\HeaderStream' => $vendorDir . '/zbateson/mail-mime-parser/src/Stream/HeaderStream.php',
'ZBateson\\MailMimeParser\\Stream\\MessagePartStream' => $vendorDir . '/zbateson/mail-mime-parser/src/Stream/MessagePartStream.php',
'ZBateson\\MailMimeParser\\Stream\\MessagePartStreamDecorator' => $vendorDir . '/zbateson/mail-mime-parser/src/Stream/MessagePartStreamDecorator.php',
'ZBateson\\MailMimeParser\\Stream\\MessagePartStreamReadException' => $vendorDir . '/zbateson/mail-mime-parser/src/Stream/MessagePartStreamReadException.php',
'ZBateson\\MailMimeParser\\Stream\\StreamFactory' => $vendorDir . '/zbateson/mail-mime-parser/src/Stream/StreamFactory.php',
'ZBateson\\MbWrapper\\MbWrapper' => $vendorDir . '/zbateson/mb-wrapper/src/MbWrapper.php',
'ZBateson\\MbWrapper\\UnsupportedCharsetException' => $vendorDir . '/zbateson/mb-wrapper/src/UnsupportedCharsetException.php',
'ZBateson\\StreamDecorators\\Base64Stream' => $vendorDir . '/zbateson/stream-decorators/src/Base64Stream.php',
'ZBateson\\StreamDecorators\\CharsetStream' => $vendorDir . '/zbateson/stream-decorators/src/CharsetStream.php',
'ZBateson\\StreamDecorators\\ChunkSplitStream' => $vendorDir . '/zbateson/stream-decorators/src/ChunkSplitStream.php',
'ZBateson\\StreamDecorators\\DecoratedCachingStream' => $vendorDir . '/zbateson/stream-decorators/src/DecoratedCachingStream.php',
'ZBateson\\StreamDecorators\\NonClosingStream' => $vendorDir . '/zbateson/stream-decorators/src/NonClosingStream.php',
'ZBateson\\StreamDecorators\\PregReplaceFilterStream' => $vendorDir . '/zbateson/stream-decorators/src/PregReplaceFilterStream.php',
'ZBateson\\StreamDecorators\\QuotedPrintableStream' => $vendorDir . '/zbateson/stream-decorators/src/QuotedPrintableStream.php',
'ZBateson\\StreamDecorators\\SeekingLimitStream' => $vendorDir . '/zbateson/stream-decorators/src/SeekingLimitStream.php',
'ZBateson\\StreamDecorators\\TellZeroStream' => $vendorDir . '/zbateson/stream-decorators/src/TellZeroStream.php',
'ZBateson\\StreamDecorators\\UUStream' => $vendorDir . '/zbateson/stream-decorators/src/UUStream.php',
);

View File

@@ -6,22 +6,19 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php',
'2203a247e6fda86070a5e4e07aed533a' => $vendorDir . '/symfony/clock/Resources/now.php',
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'b33e3d135e5d9e47d845c576147bda89' => $vendorDir . '/php-di/php-di/src/functions.php',
'606a39d89246991a373564698c2d8383' => $vendorDir . '/symfony/polyfill-php85/bootstrap.php',
'9d2b9fc6db0f153a0a149fefb182415e' => $vendorDir . '/symfony/polyfill-php84/bootstrap.php',
'23f09fe3194f8c2f70923f90d6702129' => $vendorDir . '/illuminate/collections/functions.php',
'60799491728b879e74601d83e38b2cad' => $vendorDir . '/illuminate/collections/helpers.php',
'2203a247e6fda86070a5e4e07aed533a' => $vendorDir . '/symfony/clock/Resources/now.php',
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'19e6faa27d773988183e0f384143fcad' => $vendorDir . '/illuminate/reflection/helpers.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'f625ee536139dfb962a398b200bdb2bd' => $vendorDir . '/illuminate/support/functions.php',
'72579e7bd17821bb1321b87411366eae' => $vendorDir . '/illuminate/support/helpers.php',
'b33e3d135e5d9e47d845c576147bda89' => $vendorDir . '/php-di/php-di/src/functions.php',
);

View File

@@ -6,11 +6,9 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'voku\\' => array($vendorDir . '/voku/portable-ascii/src/voku'),
'ZBateson\\StreamDecorators\\' => array($vendorDir . '/zbateson/stream-decorators/src'),
'ZBateson\\MbWrapper\\' => array($vendorDir . '/zbateson/mb-wrapper/src'),
'ZBateson\\MailMimeParser\\' => array($vendorDir . '/zbateson/mail-mime-parser/src'),
'Webklex\\PHPIMAP\\' => array($vendorDir . '/webklex/php-imap/src'),
'Symfony\\Polyfill\\Php85\\' => array($vendorDir . '/symfony/polyfill-php85'),
'Symfony\\Polyfill\\Php84\\' => array($vendorDir . '/symfony/polyfill-php84'),
'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'),
@@ -22,21 +20,18 @@ return array(
'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'),
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
'Symfony\\Component\\Mime\\' => array($vendorDir . '/symfony/mime'),
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
'Symfony\\Component\\Clock\\' => array($vendorDir . '/symfony/clock'),
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Psr\\Clock\\' => array($vendorDir . '/psr/clock/src'),
'Laravel\\SerializableClosure\\' => array($vendorDir . '/laravel/serializable-closure/src'),
'Invoker\\' => array($vendorDir . '/php-di/invoker/src'),
'Illuminate\\Support\\' => array($vendorDir . '/illuminate/reflection', $vendorDir . '/illuminate/macroable', $vendorDir . '/illuminate/conditionable', $vendorDir . '/illuminate/collections', $vendorDir . '/illuminate/support'),
'Illuminate\\Pagination\\' => array($vendorDir . '/illuminate/pagination'),
'Illuminate\\Support\\' => array($vendorDir . '/illuminate/macroable', $vendorDir . '/illuminate/conditionable', $vendorDir . '/illuminate/collections'),
'Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'Egulias\\EmailValidator\\' => array($vendorDir . '/egulias/email-validator/src'),
'Doctrine\\Inflector\\' => array($vendorDir . '/doctrine/inflector/src'),
'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/src'),
'DirectoryTree\\ImapEngine\\' => array($vendorDir . '/directorytree/imapengine/src'),
'DI\\' => array($vendorDir . '/php-di/php-di/src'),

View File

@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit9b9826e5b5cc7806cd328c4112cca75e
class ComposerAutoloaderInitc3c4b7d024f8d7c21b5ca31de3cb6066
{
private static $loader;
@@ -24,15 +24,15 @@ class ComposerAutoloaderInit9b9826e5b5cc7806cd328c4112cca75e
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit9b9826e5b5cc7806cd328c4112cca75e', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInitc3c4b7d024f8d7c21b5ca31de3cb6066', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit9b9826e5b5cc7806cd328c4112cca75e', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInitc3c4b7d024f8d7c21b5ca31de3cb6066', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit9b9826e5b5cc7806cd328c4112cca75e::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInitc3c4b7d024f8d7c21b5ca31de3cb6066::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
@@ -53,12 +53,12 @@ class ComposerAutoloaderInit9b9826e5b5cc7806cd328c4112cca75e
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit9b9826e5b5cc7806cd328c4112cca75e::$files;
$includeFiles = Composer\Autoload\ComposerStaticInitc3c4b7d024f8d7c21b5ca31de3cb6066::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire9b9826e5b5cc7806cd328c4112cca75e($fileIdentifier, $file);
composerRequirec3c4b7d024f8d7c21b5ca31de3cb6066($fileIdentifier, $file);
}
return $loader;
@@ -70,7 +70,7 @@ class ComposerAutoloaderInit9b9826e5b5cc7806cd328c4112cca75e
* @param string $file
* @return void
*/
function composerRequire9b9826e5b5cc7806cd328c4112cca75e($fileIdentifier, $file)
function composerRequirec3c4b7d024f8d7c21b5ca31de3cb6066($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

File diff suppressed because it is too large Load Diff

View File

@@ -74,17 +74,17 @@
},
{
"name": "directorytree/imapengine",
"version": "v1.24.1",
"version_normalized": "1.24.1.0",
"version": "v1.25.0",
"version_normalized": "1.25.0.0",
"source": {
"type": "git",
"url": "https://github.com/DirectoryTree/ImapEngine.git",
"reference": "d545ff3f6d2155ce7f9f612f0444579477d7bab8"
"reference": "ac8a4d028334c2d3a4bc8fd975317a75cd968a47"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/DirectoryTree/ImapEngine/zipball/d545ff3f6d2155ce7f9f612f0444579477d7bab8",
"reference": "d545ff3f6d2155ce7f9f612f0444579477d7bab8",
"url": "https://api.github.com/repos/DirectoryTree/ImapEngine/zipball/ac8a4d028334c2d3a4bc8fd975317a75cd968a47",
"reference": "ac8a4d028334c2d3a4bc8fd975317a75cd968a47",
"shasum": ""
},
"require": {
@@ -99,7 +99,7 @@
"pestphp/pest": "^2.0|^3.0|^4.0",
"spatie/ray": "^1.0"
},
"time": "2026-05-20T13:36:53+00:00",
"time": "2026-06-19T17:03:06+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -127,7 +127,7 @@
],
"support": {
"issues": "https://github.com/DirectoryTree/ImapEngine/issues",
"source": "https://github.com/DirectoryTree/ImapEngine/tree/v1.24.1"
"source": "https://github.com/DirectoryTree/ImapEngine/tree/v1.25.0"
},
"funding": [
{
@@ -137,99 +137,6 @@
],
"install-path": "../directorytree/imapengine"
},
{
"name": "doctrine/inflector",
"version": "2.1.0",
"version_normalized": "2.1.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b",
"reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^12.0 || ^13.0",
"phpstan/phpstan": "^1.12 || ^2.0",
"phpstan/phpstan-phpunit": "^1.4 || ^2.0",
"phpstan/phpstan-strict-rules": "^1.6 || ^2.0",
"phpunit/phpunit": "^8.5 || ^12.2"
},
"time": "2025-08-10T19:31:58+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Doctrine\\Inflector\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
"keywords": [
"inflection",
"inflector",
"lowercase",
"manipulation",
"php",
"plural",
"singular",
"strings",
"uppercase",
"words"
],
"support": {
"issues": "https://github.com/doctrine/inflector/issues",
"source": "https://github.com/doctrine/inflector/tree/2.1.0"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
"type": "tidelift"
}
],
"install-path": "../doctrine/inflector"
},
{
"name": "doctrine/lexer",
"version": "3.0.1",
@@ -382,17 +289,17 @@
},
{
"name": "guzzlehttp/psr7",
"version": "2.11.0",
"version_normalized": "2.11.0.0",
"version": "2.12.3",
"version_normalized": "2.12.3.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "bbb5e61349fa5cb822b3e87842b951088b76b81f"
"reference": "7ec62dc3f44aa218487dbed81a9bf9bc647be55d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/bbb5e61349fa5cb822b3e87842b951088b76b81f",
"reference": "bbb5e61349fa5cb822b3e87842b951088b76b81f",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/7ec62dc3f44aa218487dbed81a9bf9bc647be55d",
"reference": "7ec62dc3f44aa218487dbed81a9bf9bc647be55d",
"shasum": ""
},
"require": {
@@ -401,7 +308,7 @@
"psr/http-message": "^1.1 || ^2.0",
"ralouphie/getallheaders": "^3.0",
"symfony/deprecation-contracts": "^2.5 || ^3.0",
"symfony/polyfill-php80": "^1.24"
"symfony/polyfill-php80": "^1.25"
},
"provide": {
"psr/http-factory-implementation": "1.0",
@@ -416,7 +323,7 @@
"suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
},
"time": "2026-06-02T12:30:48+00:00",
"time": "2026-06-23T15:21:08+00:00",
"type": "library",
"extra": {
"bamarni-bin": {
@@ -484,7 +391,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.11.0"
"source": "https://github.com/guzzle/psr7/tree/2.12.3"
},
"funding": [
{
@@ -714,196 +621,6 @@
},
"install-path": "../illuminate/macroable"
},
{
"name": "illuminate/pagination",
"version": "v12.62.0",
"version_normalized": "12.62.0.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/pagination.git",
"reference": "8327d828676654053906a771abf5eea5426354ec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/pagination/zipball/8327d828676654053906a771abf5eea5426354ec",
"reference": "8327d828676654053906a771abf5eea5426354ec",
"shasum": ""
},
"require": {
"ext-filter": "*",
"illuminate/collections": "^12.0",
"illuminate/contracts": "^12.0",
"illuminate/support": "^12.0",
"php": "^8.2"
},
"time": "2026-02-25T15:25:18+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "12.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Illuminate\\Pagination\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Pagination package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"install-path": "../illuminate/pagination"
},
{
"name": "illuminate/reflection",
"version": "v12.62.0",
"version_normalized": "12.62.0.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/reflection.git",
"reference": "348cf5da9de89b596d7723be6425fb048e2bf4bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/reflection/zipball/348cf5da9de89b596d7723be6425fb048e2bf4bb",
"reference": "348cf5da9de89b596d7723be6425fb048e2bf4bb",
"shasum": ""
},
"require": {
"illuminate/collections": "^12.0",
"illuminate/contracts": "^12.0",
"php": "^8.2"
},
"time": "2026-02-25T15:25:18+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "12.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"helpers.php"
],
"psr-4": {
"Illuminate\\Support\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Reflection package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"install-path": "../illuminate/reflection"
},
{
"name": "illuminate/support",
"version": "v12.62.0",
"version_normalized": "12.62.0.0",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
"reference": "3a8772095ef7d6b1961a77f2f0b8921c056c48ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/support/zipball/3a8772095ef7d6b1961a77f2f0b8921c056c48ea",
"reference": "3a8772095ef7d6b1961a77f2f0b8921c056c48ea",
"shasum": ""
},
"require": {
"doctrine/inflector": "^2.0",
"ext-ctype": "*",
"ext-filter": "*",
"ext-mbstring": "*",
"illuminate/collections": "^12.0",
"illuminate/conditionable": "^12.0",
"illuminate/contracts": "^12.0",
"illuminate/macroable": "^12.0",
"illuminate/reflection": "^12.0",
"nesbot/carbon": "^3.8.4",
"php": "^8.2",
"symfony/polyfill-php83": "^1.33",
"symfony/polyfill-php85": "^1.33",
"voku/portable-ascii": "^2.0.2"
},
"conflict": {
"tightenco/collect": "<5.5.33"
},
"replace": {
"spatie/once": "*"
},
"suggest": {
"illuminate/filesystem": "Required to use the Composer class (^12.0).",
"laravel/serializable-closure": "Required to use the once function (^1.3|^2.0).",
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.7).",
"league/uri": "Required to use the Uri class (^7.5.1).",
"ramsey/uuid": "Required to use Str::uuid() (^4.7).",
"symfony/process": "Required to use the Composer class (^7.2).",
"symfony/uid": "Required to use Str::ulid() (^7.2).",
"symfony/var-dumper": "Required to use the dd function (^7.2).",
"vlucas/phpdotenv": "Required to use the Env class and env helper (^5.6.1)."
},
"time": "2026-05-31T22:10:17+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "12.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"functions.php",
"helpers.php"
],
"psr-4": {
"Illuminate\\Support\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "The Illuminate Support package.",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"install-path": "../illuminate/support"
},
{
"name": "laravel/serializable-closure",
"version": "v2.0.13",
@@ -970,17 +687,17 @@
},
{
"name": "nesbot/carbon",
"version": "3.11.4",
"version_normalized": "3.11.4.0",
"version": "3.13.0",
"version_normalized": "3.13.0.0",
"source": {
"type": "git",
"url": "https://github.com/CarbonPHP/carbon.git",
"reference": "e890471a3494740f7d9326d72ce6a8c559ffee60"
"reference": "40f6618f052df16b545f626fbf9a878e6497d16a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/e890471a3494740f7d9326d72ce6a8c559ffee60",
"reference": "e890471a3494740f7d9326d72ce6a8c559ffee60",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/40f6618f052df16b545f626fbf9a878e6497d16a",
"reference": "40f6618f052df16b545f626fbf9a878e6497d16a",
"shasum": ""
},
"require": {
@@ -1006,7 +723,7 @@
"phpunit/phpunit": "^10.5.53",
"squizlabs/php_codesniffer": "^3.13.4 || ^4.0.0"
},
"time": "2026-04-07T09:57:54+00:00",
"time": "2026-06-18T13:49:15+00:00",
"bin": [
"bin/carbon"
],
@@ -1740,91 +1457,6 @@
],
"install-path": "../symfony/deprecation-contracts"
},
{
"name": "symfony/http-foundation",
"version": "v7.4.13",
"version_normalized": "7.4.13.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "bc354f47c62301e990b7874fa662326368508e2c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/bc354f47c62301e990b7874fa662326368508e2c",
"reference": "bc354f47c62301e990b7874fa662326368508e2c",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "^1.1"
},
"conflict": {
"doctrine/dbal": "<3.6",
"symfony/cache": "<6.4.12|>=7.0,<7.1.5"
},
"require-dev": {
"doctrine/dbal": "^3.6|^4",
"predis/predis": "^1.1|^2.0",
"symfony/cache": "^6.4.12|^7.1.5|^8.0",
"symfony/clock": "^6.4|^7.0|^8.0",
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
"symfony/expression-language": "^6.4|^7.0|^8.0",
"symfony/http-kernel": "^6.4|^7.0|^8.0",
"symfony/mime": "^6.4|^7.0|^8.0",
"symfony/rate-limiter": "^6.4|^7.0|^8.0"
},
"time": "2026-05-24T11:20:33+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Component\\HttpFoundation\\": ""
},
"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": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-foundation/tree/v7.4.13"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"install-path": "../symfony/http-foundation"
},
{
"name": "symfony/mime",
"version": "v7.4.13",
@@ -2794,180 +2426,19 @@
],
"install-path": "../symfony/translation-contracts"
},
{
"name": "voku/portable-ascii",
"version": "2.1.1",
"version_normalized": "2.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/voku/portable-ascii.git",
"reference": "8e1051fe39379367aecf014f41744ce7539a856f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/voku/portable-ascii/zipball/8e1051fe39379367aecf014f41744ce7539a856f",
"reference": "8e1051fe39379367aecf014f41744ce7539a856f",
"shasum": ""
},
"require": {
"php": ">=7.1.0"
},
"require-dev": {
"phpunit/phpunit": "~8.5 || ~9.6 || ~10.5 || ~11.5"
},
"suggest": {
"ext-intl": "Use Intl for transliterator_transliterate() support"
},
"time": "2026-04-26T05:33:54+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"voku\\": "src/voku/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Lars Moelleken",
"homepage": "https://www.moelleken.org/"
}
],
"description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
"homepage": "https://github.com/voku/portable-ascii",
"keywords": [
"ascii",
"clean",
"php"
],
"support": {
"issues": "https://github.com/voku/portable-ascii/issues",
"source": "https://github.com/voku/portable-ascii/tree/2.1.1"
},
"funding": [
{
"url": "https://www.paypal.me/moelleken",
"type": "custom"
},
{
"url": "https://github.com/voku",
"type": "github"
},
{
"url": "https://opencollective.com/portable-ascii",
"type": "open_collective"
},
{
"url": "https://www.patreon.com/voku",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
"type": "tidelift"
}
],
"install-path": "../voku/portable-ascii"
},
{
"name": "webklex/php-imap",
"version": "6.2.0",
"version_normalized": "6.2.0.0",
"source": {
"type": "git",
"url": "https://github.com/Webklex/php-imap.git",
"reference": "6b8ef85d621bbbaf52741b00cca8e9237e2b2e05"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Webklex/php-imap/zipball/6b8ef85d621bbbaf52741b00cca8e9237e2b2e05",
"reference": "6b8ef85d621bbbaf52741b00cca8e9237e2b2e05",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"ext-iconv": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-zip": "*",
"illuminate/pagination": ">=5.0.0",
"nesbot/carbon": "^2.62.1|^3.2.4",
"php": "^8.0.2",
"symfony/http-foundation": ">=2.8.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5.10"
},
"suggest": {
"symfony/mime": "Recomended for better extension support",
"symfony/var-dumper": "Usefull tool for debugging"
},
"time": "2025-04-25T06:02:37+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.0-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Webklex\\PHPIMAP\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Malte Goldenbaum",
"email": "github@webklex.com",
"role": "Developer"
}
],
"description": "PHP IMAP client",
"homepage": "https://github.com/webklex/php-imap",
"keywords": [
"imap",
"mail",
"php-imap",
"pop3",
"webklex"
],
"support": {
"issues": "https://github.com/Webklex/php-imap/issues",
"source": "https://github.com/Webklex/php-imap/tree/6.2.0"
},
"funding": [
{
"url": "https://www.buymeacoffee.com/webklex",
"type": "custom"
},
{
"url": "https://ko-fi.com/webklex",
"type": "ko_fi"
}
],
"install-path": "../webklex/php-imap"
},
{
"name": "zbateson/mail-mime-parser",
"version": "3.0.5",
"version_normalized": "3.0.5.0",
"version": "3.0.6",
"version_normalized": "3.0.6.0",
"source": {
"type": "git",
"url": "https://github.com/zbateson/mail-mime-parser.git",
"reference": "ff054c8e05310c445c2028c6128a4319cc9f6aa8"
"reference": "395c406cc1c5d1eb171d9decb0a3b509e8bd6bc0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/ff054c8e05310c445c2028c6128a4319cc9f6aa8",
"reference": "ff054c8e05310c445c2028c6128a4319cc9f6aa8",
"url": "https://api.github.com/repos/zbateson/mail-mime-parser/zipball/395c406cc1c5d1eb171d9decb0a3b509e8bd6bc0",
"reference": "395c406cc1c5d1eb171d9decb0a3b509e8bd6bc0",
"shasum": ""
},
"require": {
@@ -2988,7 +2459,7 @@
"ext-iconv": "For best support/performance",
"ext-mbstring": "For best support/performance"
},
"time": "2025-12-02T00:29:16+00:00",
"time": "2026-06-24T13:42:46+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -3173,6 +2644,6 @@
"install-path": "../zbateson/stream-decorators"
}
],
"dev": true,
"dev": false,
"dev-package-names": []
}

View File

@@ -5,9 +5,9 @@
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '2204bd52f45d06ee1ec2b39342b3cf74bd8a2c8b',
'reference' => '63ad3256ee5a661d2a34105ed69d198f585a025a',
'name' => '__root__',
'dev' => true,
'dev' => false,
),
'versions' => array(
'__root__' => array(
@@ -16,7 +16,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '2204bd52f45d06ee1ec2b39342b3cf74bd8a2c8b',
'reference' => '63ad3256ee5a661d2a34105ed69d198f585a025a',
'dev_requirement' => false,
),
'carbonphp/carbon-doctrine-types' => array(
@@ -29,21 +29,12 @@
'dev_requirement' => false,
),
'directorytree/imapengine' => array(
'pretty_version' => 'v1.24.1',
'version' => '1.24.1.0',
'pretty_version' => 'v1.25.0',
'version' => '1.25.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../directorytree/imapengine',
'aliases' => array(),
'reference' => 'd545ff3f6d2155ce7f9f612f0444579477d7bab8',
'dev_requirement' => false,
),
'doctrine/inflector' => array(
'pretty_version' => '2.1.0',
'version' => '2.1.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../doctrine/inflector',
'aliases' => array(),
'reference' => '6d6c96277ea252fc1304627204c3d5e6e15faa3b',
'reference' => 'ac8a4d028334c2d3a4bc8fd975317a75cd968a47',
'dev_requirement' => false,
),
'doctrine/lexer' => array(
@@ -65,12 +56,12 @@
'dev_requirement' => false,
),
'guzzlehttp/psr7' => array(
'pretty_version' => '2.11.0',
'version' => '2.11.0.0',
'pretty_version' => '2.12.3',
'version' => '2.12.3.0',
'type' => 'library',
'install_path' => __DIR__ . '/../guzzlehttp/psr7',
'aliases' => array(),
'reference' => 'bbb5e61349fa5cb822b3e87842b951088b76b81f',
'reference' => '7ec62dc3f44aa218487dbed81a9bf9bc647be55d',
'dev_requirement' => false,
),
'illuminate/collections' => array(
@@ -109,33 +100,6 @@
'reference' => 'e295d62d89dcdb87e2b1bd70dd14d074a0ed73cc',
'dev_requirement' => false,
),
'illuminate/pagination' => array(
'pretty_version' => 'v12.62.0',
'version' => '12.62.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/pagination',
'aliases' => array(),
'reference' => '8327d828676654053906a771abf5eea5426354ec',
'dev_requirement' => false,
),
'illuminate/reflection' => array(
'pretty_version' => 'v12.62.0',
'version' => '12.62.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/reflection',
'aliases' => array(),
'reference' => '348cf5da9de89b596d7723be6425fb048e2bf4bb',
'dev_requirement' => false,
),
'illuminate/support' => array(
'pretty_version' => 'v12.62.0',
'version' => '12.62.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/support',
'aliases' => array(),
'reference' => '3a8772095ef7d6b1961a77f2f0b8921c056c48ea',
'dev_requirement' => false,
),
'laravel/serializable-closure' => array(
'pretty_version' => 'v2.0.13',
'version' => '2.0.13.0',
@@ -146,12 +110,12 @@
'dev_requirement' => false,
),
'nesbot/carbon' => array(
'pretty_version' => '3.11.4',
'version' => '3.11.4.0',
'pretty_version' => '3.13.0',
'version' => '3.13.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../nesbot/carbon',
'aliases' => array(),
'reference' => 'e890471a3494740f7d9326d72ce6a8c559ffee60',
'reference' => '40f6618f052df16b545f626fbf9a878e6497d16a',
'dev_requirement' => false,
),
'php-di/invoker' => array(
@@ -259,12 +223,6 @@
'reference' => '120b605dfeb996808c31b6477290a714d356e822',
'dev_requirement' => false,
),
'spatie/once' => array(
'dev_requirement' => false,
'replaced' => array(
0 => '*',
),
),
'symfony/clock' => array(
'pretty_version' => 'v7.4.8',
'version' => '7.4.8.0',
@@ -283,15 +241,6 @@
'reference' => '50f59d1f3ca46d41ac911f97a78626b6756af35b',
'dev_requirement' => false,
),
'symfony/http-foundation' => array(
'pretty_version' => 'v7.4.13',
'version' => '7.4.13.0',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/http-foundation',
'aliases' => array(),
'reference' => 'bc354f47c62301e990b7874fa662326368508e2c',
'dev_requirement' => false,
),
'symfony/mime' => array(
'pretty_version' => 'v7.4.13',
'version' => '7.4.13.0',
@@ -397,31 +346,13 @@
0 => '2.3|3.0',
),
),
'voku/portable-ascii' => array(
'pretty_version' => '2.1.1',
'version' => '2.1.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../voku/portable-ascii',
'aliases' => array(),
'reference' => '8e1051fe39379367aecf014f41744ce7539a856f',
'dev_requirement' => false,
),
'webklex/php-imap' => array(
'pretty_version' => '6.2.0',
'version' => '6.2.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../webklex/php-imap',
'aliases' => array(),
'reference' => '6b8ef85d621bbbaf52741b00cca8e9237e2b2e05',
'dev_requirement' => false,
),
'zbateson/mail-mime-parser' => array(
'pretty_version' => '3.0.5',
'version' => '3.0.5.0',
'pretty_version' => '3.0.6',
'version' => '3.0.6.0',
'type' => 'library',
'install_path' => __DIR__ . '/../zbateson/mail-mime-parser',
'aliases' => array(),
'reference' => 'ff054c8e05310c445c2028c6128a4319cc9f6aa8',
'reference' => '395c406cc1c5d1eb171d9decb0a3b509e8bd6bc0',
'dev_requirement' => false,
),
'zbateson/mb-wrapper' => array(

View File

@@ -270,6 +270,14 @@ class ImapQueryBuilder
return $this->where(ImapSearchKey::Header->value." $header", $value);
}
/**
* Add a where "HEADER Message-ID" clause to the query.
*/
public function messageId(string $messageId): static
{
return $this->header('Message-ID', trim(trim($messageId), '<>'));
}
/**
* Add a where "UID" clause to the query.
*/

View File

@@ -1,19 +0,0 @@
Copyright (c) 2006-2015 Doctrine Project
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.

View File

@@ -1,7 +0,0 @@
# Doctrine Inflector
Doctrine Inflector is a small library that can perform string manipulations
with regard to uppercase/lowercase and singular/plural forms of words.
[![Build Status](https://github.com/doctrine/inflector/workflows/Continuous%20Integration/badge.svg)](https://github.com/doctrine/inflector/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A4.0.x)
[![Code Coverage](https://codecov.io/gh/doctrine/inflector/branch/2.0.x/graph/badge.svg)](https://codecov.io/gh/doctrine/inflector/branch/2.0.x)

View File

@@ -1,67 +0,0 @@
{
"name": "doctrine/inflector",
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
"license": "MIT",
"type": "library",
"keywords": [
"php",
"strings",
"words",
"manipulation",
"inflector",
"inflection",
"uppercase",
"lowercase",
"singular",
"plural"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^12.0 || ^13.0",
"phpstan/phpstan": "^1.12 || ^2.0",
"phpstan/phpstan-phpunit": "^1.4 || ^2.0",
"phpstan/phpstan-strict-rules": "^1.6 || ^2.0",
"phpunit/phpunit": "^8.5 || ^12.2"
},
"autoload": {
"psr-4": {
"Doctrine\\Inflector\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Doctrine\\Tests\\Inflector\\": "tests"
}
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
},
"sort-packages": true
}
}

View File

@@ -1,227 +0,0 @@
Introduction
============
The Doctrine Inflector has methods for inflecting text. The features include pluralization,
singularization, converting between camelCase and under_score and capitalizing
words.
Installation
============
You can install the Inflector with composer:
.. code-block:: console
$ composer require doctrine/inflector
Usage
=====
Using the inflector is easy, you can create a new ``Doctrine\Inflector\Inflector`` instance by using
the ``Doctrine\Inflector\InflectorFactory`` class:
.. code-block:: php
use Doctrine\Inflector\InflectorFactory;
$inflector = InflectorFactory::create()->build();
By default it will create an English inflector. If you want to use another language, just pass the language
you want to create an inflector for to the ``createForLanguage()`` method:
.. code-block:: php
use Doctrine\Inflector\InflectorFactory;
use Doctrine\Inflector\Language;
$inflector = InflectorFactory::createForLanguage(Language::SPANISH)->build();
The supported languages are as follows:
- ``Language::ENGLISH``
- ``Language::ESPERANTO``
- ``Language::FRENCH``
- ``Language::NORWEGIAN_BOKMAL``
- ``Language::PORTUGUESE``
- ``Language::SPANISH``
- ``Language::TURKISH``
If you want to manually construct the inflector instead of using a factory, you can do so like this:
.. code-block:: php
use Doctrine\Inflector\CachedWordInflector;
use Doctrine\Inflector\RulesetInflector;
use Doctrine\Inflector\Rules\English;
$inflector = new Inflector(
new CachedWordInflector(new RulesetInflector(
English\Rules::getSingularRuleset()
)),
new CachedWordInflector(new RulesetInflector(
English\Rules::getPluralRuleset()
))
);
Adding Languages
----------------
If you are interested in adding support for your language, take a look at the other languages defined in the
``Doctrine\Inflector\Rules`` namespace and the tests located in ``Doctrine\Tests\Inflector\Rules``. You can copy
one of the languages and update the rules for your language.
Once you have done this, send a pull request to the ``doctrine/inflector`` repository with the additions.
Custom Setup
============
If you want to setup custom singular and plural rules, you can configure these in the factory:
.. code-block:: php
use Doctrine\Inflector\InflectorFactory;
use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Transformations;
use Doctrine\Inflector\Rules\Word;
$inflector = InflectorFactory::create()
->withSingularRules(
new Ruleset(
new Transformations(
new Transformation(new Pattern('/^(bil)er$/i'), '\1'),
new Transformation(new Pattern('/^(inflec|contribu)tors$/i'), '\1ta')
),
new Patterns(new Pattern('singulars')),
new Substitutions(new Substitution(new Word('spins'), new Word('spinor')))
)
)
->withPluralRules(
new Ruleset(
new Transformations(
new Transformation(new Pattern('^(bil)er$'), '\1'),
new Transformation(new Pattern('^(inflec|contribu)tors$'), '\1ta')
),
new Patterns(new Pattern('noflect'), new Pattern('abtuse')),
new Substitutions(
new Substitution(new Word('amaze'), new Word('amazable')),
new Substitution(new Word('phone'), new Word('phonezes'))
)
)
)
->build();
No operation inflector
----------------------
The ``Doctrine\Inflector\NoopWordInflector`` may be used to configure an inflector that doesn't perform any operation for
pluralization and/or singularization. If will simply return the input as output.
This is an implementation of the `Null Object design pattern <https://sourcemaking.com/design_patterns/null_object>`_.
.. code-block:: php
use Doctrine\Inflector\Inflector;
use Doctrine\Inflector\NoopWordInflector;
$inflector = new Inflector(new NoopWordInflector(), new NoopWordInflector());
Tableize
========
Converts ``ModelName`` to ``model_name``:
.. code-block:: php
echo $inflector->tableize('ModelName'); // model_name
Classify
========
Converts ``model_name`` to ``ModelName``:
.. code-block:: php
echo $inflector->classify('model_name'); // ModelName
Camelize
========
This method uses `Classify`_ and then converts the first character to lowercase:
.. code-block:: php
echo $inflector->camelize('model_name'); // modelName
Capitalize
==========
Takes a string and capitalizes all of the words, like PHP's built-in
``ucwords`` function. This extends that behavior, however, by allowing the
word delimiters to be configured, rather than only separating on
whitespace.
Here is an example:
.. code-block:: php
$string = 'top-o-the-morning to all_of_you!';
echo $inflector->capitalize($string); // Top-O-The-Morning To All_of_you!
echo $inflector->capitalize($string, '-_ '); // Top-O-The-Morning To All_Of_You!
Pluralize
=========
Returns a word in plural form.
.. code-block:: php
echo $inflector->pluralize('browser'); // browsers
Singularize
===========
Returns a word in singular form.
.. code-block:: php
echo $inflector->singularize('browsers'); // browser
Urlize
======
Generate a URL friendly string from a string of text:
.. code-block:: php
echo $inflector->urlize('My first blog post'); // my-first-blog-post
Unaccent
========
You can unaccent a string of text using the ``unaccent()`` method:
.. code-block:: php
echo $inflector->unaccent('año'); // ano
Legacy API
==========
The API present in Inflector 1.x is still available, but will be deprecated in a future release and dropped for 3.0.
Support for languages other than English is available in the 2.0 API only.
Acknowledgements
================
The language rules in this library have been adapted from several different sources, including but not limited to:
- `Ruby On Rails Inflector <http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html>`_
- `ICanBoogie Inflector <https://github.com/ICanBoogie/Inflector>`_
- `CakePHP Inflector <https://book.cakephp.org/3.0/en/core-libraries/inflector.html>`_

View File

@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector;
class CachedWordInflector implements WordInflector
{
/** @var WordInflector */
private $wordInflector;
/** @var string[] */
private $cache = [];
public function __construct(WordInflector $wordInflector)
{
$this->wordInflector = $wordInflector;
}
public function inflect(string $word): string
{
return $this->cache[$word] ?? $this->cache[$word] = $this->wordInflector->inflect($word);
}
}

View File

@@ -1,66 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector;
use Doctrine\Inflector\Rules\Ruleset;
use function array_unshift;
abstract class GenericLanguageInflectorFactory implements LanguageInflectorFactory
{
/** @var Ruleset[] */
private $singularRulesets = [];
/** @var Ruleset[] */
private $pluralRulesets = [];
final public function __construct()
{
$this->singularRulesets[] = $this->getSingularRuleset();
$this->pluralRulesets[] = $this->getPluralRuleset();
}
final public function build(): Inflector
{
return new Inflector(
new CachedWordInflector(new RulesetInflector(
...$this->singularRulesets
)),
new CachedWordInflector(new RulesetInflector(
...$this->pluralRulesets
))
);
}
final public function withSingularRules(?Ruleset $singularRules, bool $reset = false): LanguageInflectorFactory
{
if ($reset) {
$this->singularRulesets = [];
}
if ($singularRules instanceof Ruleset) {
array_unshift($this->singularRulesets, $singularRules);
}
return $this;
}
final public function withPluralRules(?Ruleset $pluralRules, bool $reset = false): LanguageInflectorFactory
{
if ($reset) {
$this->pluralRulesets = [];
}
if ($pluralRules instanceof Ruleset) {
array_unshift($this->pluralRulesets, $pluralRules);
}
return $this;
}
abstract protected function getSingularRuleset(): Ruleset;
abstract protected function getPluralRuleset(): Ruleset;
}

View File

@@ -1,507 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector;
use RuntimeException;
use function chr;
use function function_exists;
use function lcfirst;
use function mb_strtolower;
use function ord;
use function preg_match;
use function preg_replace;
use function sprintf;
use function str_replace;
use function strlen;
use function strtolower;
use function strtr;
use function trim;
use function ucwords;
class Inflector
{
private const ACCENTED_CHARACTERS = [
'À' => 'A',
'Á' => 'A',
'Â' => 'A',
'Ã' => 'A',
'Ä' => 'Ae',
'Æ' => 'Ae',
'Å' => 'Aa',
'æ' => 'a',
'Ç' => 'C',
'È' => 'E',
'É' => 'E',
'Ê' => 'E',
'Ë' => 'E',
'Ì' => 'I',
'Í' => 'I',
'Î' => 'I',
'Ï' => 'I',
'Ñ' => 'N',
'Ò' => 'O',
'Ó' => 'O',
'Ô' => 'O',
'Õ' => 'O',
'Ö' => 'Oe',
'Ù' => 'U',
'Ú' => 'U',
'Û' => 'U',
'Ü' => 'Ue',
'Ý' => 'Y',
'ß' => 'ss',
'à' => 'a',
'á' => 'a',
'â' => 'a',
'ã' => 'a',
'ä' => 'ae',
'å' => 'aa',
'ç' => 'c',
'è' => 'e',
'é' => 'e',
'ê' => 'e',
'ë' => 'e',
'ì' => 'i',
'í' => 'i',
'î' => 'i',
'ï' => 'i',
'ñ' => 'n',
'ò' => 'o',
'ó' => 'o',
'ô' => 'o',
'õ' => 'o',
'ö' => 'oe',
'ù' => 'u',
'ú' => 'u',
'û' => 'u',
'ü' => 'ue',
'ý' => 'y',
'ÿ' => 'y',
'Ā' => 'A',
'ā' => 'a',
'Ă' => 'A',
'ă' => 'a',
'Ą' => 'A',
'ą' => 'a',
'Ć' => 'C',
'ć' => 'c',
'Ĉ' => 'C',
'ĉ' => 'c',
'Ċ' => 'C',
'ċ' => 'c',
'Č' => 'C',
'č' => 'c',
'Ď' => 'D',
'ď' => 'd',
'Đ' => 'D',
'đ' => 'd',
'Ē' => 'E',
'ē' => 'e',
'Ĕ' => 'E',
'ĕ' => 'e',
'Ė' => 'E',
'ė' => 'e',
'Ę' => 'E',
'ę' => 'e',
'Ě' => 'E',
'ě' => 'e',
'Ĝ' => 'G',
'ĝ' => 'g',
'Ğ' => 'G',
'ğ' => 'g',
'Ġ' => 'G',
'ġ' => 'g',
'Ģ' => 'G',
'ģ' => 'g',
'Ĥ' => 'H',
'ĥ' => 'h',
'Ħ' => 'H',
'ħ' => 'h',
'Ĩ' => 'I',
'ĩ' => 'i',
'Ī' => 'I',
'ī' => 'i',
'Ĭ' => 'I',
'ĭ' => 'i',
'Į' => 'I',
'į' => 'i',
'İ' => 'I',
'ı' => 'i',
'IJ' => 'IJ',
'ij' => 'ij',
'Ĵ' => 'J',
'ĵ' => 'j',
'Ķ' => 'K',
'ķ' => 'k',
'ĸ' => 'k',
'Ĺ' => 'L',
'ĺ' => 'l',
'Ļ' => 'L',
'ļ' => 'l',
'Ľ' => 'L',
'ľ' => 'l',
'Ŀ' => 'L',
'ŀ' => 'l',
'Ł' => 'L',
'ł' => 'l',
'Ń' => 'N',
'ń' => 'n',
'Ņ' => 'N',
'ņ' => 'n',
'Ň' => 'N',
'ň' => 'n',
'ʼn' => 'N',
'Ŋ' => 'n',
'ŋ' => 'N',
'Ō' => 'O',
'ō' => 'o',
'Ŏ' => 'O',
'ŏ' => 'o',
'Ő' => 'O',
'ő' => 'o',
'Œ' => 'OE',
'œ' => 'oe',
'Ø' => 'O',
'ø' => 'o',
'Ŕ' => 'R',
'ŕ' => 'r',
'Ŗ' => 'R',
'ŗ' => 'r',
'Ř' => 'R',
'ř' => 'r',
'Ś' => 'S',
'ś' => 's',
'Ŝ' => 'S',
'ŝ' => 's',
'Ş' => 'S',
'ş' => 's',
'Š' => 'S',
'š' => 's',
'Ţ' => 'T',
'ţ' => 't',
'Ť' => 'T',
'ť' => 't',
'Ŧ' => 'T',
'ŧ' => 't',
'Ũ' => 'U',
'ũ' => 'u',
'Ū' => 'U',
'ū' => 'u',
'Ŭ' => 'U',
'ŭ' => 'u',
'Ů' => 'U',
'ů' => 'u',
'Ű' => 'U',
'ű' => 'u',
'Ų' => 'U',
'ų' => 'u',
'Ŵ' => 'W',
'ŵ' => 'w',
'Ŷ' => 'Y',
'ŷ' => 'y',
'Ÿ' => 'Y',
'Ź' => 'Z',
'ź' => 'z',
'Ż' => 'Z',
'ż' => 'z',
'Ž' => 'Z',
'ž' => 'z',
'ſ' => 's',
'€' => 'E',
'£' => '',
];
/** @var WordInflector */
private $singularizer;
/** @var WordInflector */
private $pluralizer;
public function __construct(WordInflector $singularizer, WordInflector $pluralizer)
{
$this->singularizer = $singularizer;
$this->pluralizer = $pluralizer;
}
/**
* Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'.
*/
public function tableize(string $word): string
{
$tableized = preg_replace('~(?<=\\w)([A-Z])~u', '_$1', $word);
if ($tableized === null) {
throw new RuntimeException(sprintf(
'preg_replace returned null for value "%s"',
$word
));
}
return mb_strtolower($tableized);
}
/**
* Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'.
*/
public function classify(string $word): string
{
return str_replace([' ', '_', '-'], '', ucwords($word, ' _-'));
}
/**
* Camelizes a word. This uses the classify() method and turns the first character to lowercase.
*/
public function camelize(string $word): string
{
return lcfirst($this->classify($word));
}
/**
* Uppercases words with configurable delimiters between words.
*
* Takes a string and capitalizes all of the words, like PHP's built-in
* ucwords function. This extends that behavior, however, by allowing the
* word delimiters to be configured, rather than only separating on
* whitespace.
*
* Here is an example:
* <code>
* <?php
* $string = 'top-o-the-morning to all_of_you!';
* echo $inflector->capitalize($string);
* // Top-O-The-Morning To All_of_you!
*
* echo $inflector->capitalize($string, '-_ ');
* // Top-O-The-Morning To All_Of_You!
* ?>
* </code>
*
* @param string $string The string to operate on.
* @param string $delimiters A list of word separators.
*
* @return string The string with all delimiter-separated words capitalized.
*/
public function capitalize(string $string, string $delimiters = " \n\t\r\0\x0B-"): string
{
return ucwords($string, $delimiters);
}
/**
* Checks if the given string seems like it has utf8 characters in it.
*
* @param string $string The string to check for utf8 characters in.
*/
public function seemsUtf8(string $string): bool
{
for ($i = 0; $i < strlen($string); $i++) {
if (ord($string[$i]) < 0x80) {
continue; // 0bbbbbbb
}
if ((ord($string[$i]) & 0xE0) === 0xC0) {
$n = 1; // 110bbbbb
} elseif ((ord($string[$i]) & 0xF0) === 0xE0) {
$n = 2; // 1110bbbb
} elseif ((ord($string[$i]) & 0xF8) === 0xF0) {
$n = 3; // 11110bbb
} elseif ((ord($string[$i]) & 0xFC) === 0xF8) {
$n = 4; // 111110bb
} elseif ((ord($string[$i]) & 0xFE) === 0xFC) {
$n = 5; // 1111110b
} else {
return false; // Does not match any model
}
for ($j = 0; $j < $n; $j++) { // n bytes matching 10bbbbbb follow ?
if (++$i === strlen($string) || ((ord($string[$i]) & 0xC0) !== 0x80)) {
return false;
}
}
}
return true;
}
/**
* Remove any illegal characters, accents, etc.
*
* @param string $string String to unaccent
*
* @return string Unaccented string
*/
public function unaccent(string $string): string
{
if (preg_match('/[\x80-\xff]/', $string) === false) {
return $string;
}
if ($this->seemsUtf8($string)) {
$string = strtr($string, self::ACCENTED_CHARACTERS);
} else {
$characters = [];
// Assume ISO-8859-1 if not UTF-8
$characters['in'] =
chr(128)
. chr(131)
. chr(138)
. chr(142)
. chr(154)
. chr(158)
. chr(159)
. chr(162)
. chr(165)
. chr(181)
. chr(192)
. chr(193)
. chr(194)
. chr(195)
. chr(196)
. chr(197)
. chr(199)
. chr(200)
. chr(201)
. chr(202)
. chr(203)
. chr(204)
. chr(205)
. chr(206)
. chr(207)
. chr(209)
. chr(210)
. chr(211)
. chr(212)
. chr(213)
. chr(214)
. chr(216)
. chr(217)
. chr(218)
. chr(219)
. chr(220)
. chr(221)
. chr(224)
. chr(225)
. chr(226)
. chr(227)
. chr(228)
. chr(229)
. chr(231)
. chr(232)
. chr(233)
. chr(234)
. chr(235)
. chr(236)
. chr(237)
. chr(238)
. chr(239)
. chr(241)
. chr(242)
. chr(243)
. chr(244)
. chr(245)
. chr(246)
. chr(248)
. chr(249)
. chr(250)
. chr(251)
. chr(252)
. chr(253)
. chr(255);
$characters['out'] = 'EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy';
$string = strtr($string, $characters['in'], $characters['out']);
$doubleChars = [];
$doubleChars['in'] = [
chr(140),
chr(156),
chr(198),
chr(208),
chr(222),
chr(223),
chr(230),
chr(240),
chr(254),
];
$doubleChars['out'] = ['OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'];
$string = str_replace($doubleChars['in'], $doubleChars['out'], $string);
}
return $string;
}
/**
* Convert any passed string to a url friendly string.
* Converts 'My first blog post' to 'my-first-blog-post'
*
* @param string $string String to urlize.
*
* @return string Urlized string.
*/
public function urlize(string $string): string
{
// Remove all non url friendly characters with the unaccent function
$unaccented = $this->unaccent($string);
if (function_exists('mb_strtolower')) {
$lowered = mb_strtolower($unaccented);
} else {
$lowered = strtolower($unaccented);
}
$replacements = [
'/\W/' => ' ',
'/([A-Z]+)([A-Z][a-z])/' => '\1_\2',
'/([a-z\d])([A-Z])/' => '\1_\2',
'/[^A-Z^a-z^0-9^\/]+/' => '-',
];
$urlized = $lowered;
foreach ($replacements as $pattern => $replacement) {
$replaced = preg_replace($pattern, $replacement, $urlized);
if ($replaced === null) {
throw new RuntimeException(sprintf(
'preg_replace returned null for value "%s"',
$urlized
));
}
$urlized = $replaced;
}
return trim($urlized, '-');
}
/**
* Returns a word in singular form.
*
* @param string $word The word in plural form.
*
* @return string The word in singular form.
*/
public function singularize(string $word): string
{
return $this->singularizer->inflect($word);
}
/**
* Returns a word in plural form.
*
* @param string $word The word in singular form.
*
* @return string The word in plural form.
*/
public function pluralize(string $word): string
{
return $this->pluralizer->inflect($word);
}
}

View File

@@ -1,60 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector;
use Doctrine\Inflector\Rules\English;
use Doctrine\Inflector\Rules\Esperanto;
use Doctrine\Inflector\Rules\French;
use Doctrine\Inflector\Rules\Italian;
use Doctrine\Inflector\Rules\NorwegianBokmal;
use Doctrine\Inflector\Rules\Portuguese;
use Doctrine\Inflector\Rules\Spanish;
use Doctrine\Inflector\Rules\Turkish;
use InvalidArgumentException;
use function sprintf;
final class InflectorFactory
{
public static function create(): LanguageInflectorFactory
{
return self::createForLanguage(Language::ENGLISH);
}
public static function createForLanguage(string $language): LanguageInflectorFactory
{
switch ($language) {
case Language::ENGLISH:
return new English\InflectorFactory();
case Language::ESPERANTO:
return new Esperanto\InflectorFactory();
case Language::FRENCH:
return new French\InflectorFactory();
case Language::ITALIAN:
return new Italian\InflectorFactory();
case Language::NORWEGIAN_BOKMAL:
return new NorwegianBokmal\InflectorFactory();
case Language::PORTUGUESE:
return new Portuguese\InflectorFactory();
case Language::SPANISH:
return new Spanish\InflectorFactory();
case Language::TURKISH:
return new Turkish\InflectorFactory();
default:
throw new InvalidArgumentException(sprintf(
'Language "%s" is not supported.',
$language
));
}
}
}

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector;
final class Language
{
public const ENGLISH = 'english';
public const ESPERANTO = 'esperanto';
public const FRENCH = 'french';
public const ITALIAN = 'italian';
public const NORWEGIAN_BOKMAL = 'norwegian-bokmal';
public const PORTUGUESE = 'portuguese';
public const SPANISH = 'spanish';
public const TURKISH = 'turkish';
private function __construct()
{
}
}

View File

@@ -1,33 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector;
use Doctrine\Inflector\Rules\Ruleset;
interface LanguageInflectorFactory
{
/**
* Applies custom rules for singularisation
*
* @param bool $reset If true, will unset default inflections for all new rules
*
* @return $this
*/
public function withSingularRules(?Ruleset $singularRules, bool $reset = false): self;
/**
* Applies custom rules for pluralisation
*
* @param bool $reset If true, will unset default inflections for all new rules
*
* @return $this
*/
public function withPluralRules(?Ruleset $pluralRules, bool $reset = false): self;
/**
* Builds the inflector instance with all applicable rules
*/
public function build(): Inflector;
}

View File

@@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector;
class NoopWordInflector implements WordInflector
{
public function inflect(string $word): string
{
return $word;
}
}

View File

@@ -1,185 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\English;
use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('(s)tatuses$'), '\1\2tatus');
yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatus');
yield new Transformation(new Pattern('(c)ampus$'), '\1\2ampus');
yield new Transformation(new Pattern('^(.*)(menu)s$'), '\1\2');
yield new Transformation(new Pattern('(quiz)zes$'), '\\1');
yield new Transformation(new Pattern('(matr)ices$'), '\1ix');
yield new Transformation(new Pattern('(vert|ind)ices$'), '\1ex');
yield new Transformation(new Pattern('^(ox)en'), '\1');
yield new Transformation(new Pattern('(alias)(es)*$'), '\1');
yield new Transformation(new Pattern('(buffal|her|potat|tomat|volcan)oes$'), '\1o');
yield new Transformation(new Pattern('(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$'), '\1us');
yield new Transformation(new Pattern('([ftw]ax)es'), '\1');
yield new Transformation(new Pattern('(analys|ax|cris|test|thes)es$'), '\1is');
yield new Transformation(new Pattern('(shoe|slave)s$'), '\1');
yield new Transformation(new Pattern('(o)es$'), '\1');
yield new Transformation(new Pattern('ouses$'), 'ouse');
yield new Transformation(new Pattern('([^a])uses$'), '\1us');
yield new Transformation(new Pattern('([m|l])ice$'), '\1ouse');
yield new Transformation(new Pattern('(x|ch|ss|sh)es$'), '\1');
yield new Transformation(new Pattern('(m)ovies$'), '\1\2ovie');
yield new Transformation(new Pattern('(s)eries$'), '\1\2eries');
yield new Transformation(new Pattern('([^aeiouy]|qu)ies$'), '\1y');
yield new Transformation(new Pattern('([lr])ves$'), '\1f');
yield new Transformation(new Pattern('(tive)s$'), '\1');
yield new Transformation(new Pattern('(hive)s$'), '\1');
yield new Transformation(new Pattern('(drive)s$'), '\1');
yield new Transformation(new Pattern('(dive)s$'), '\1');
yield new Transformation(new Pattern('(olive)s$'), '\1');
yield new Transformation(new Pattern('([^fo])ves$'), '\1fe');
yield new Transformation(new Pattern('(^analy)ses$'), '\1sis');
yield new Transformation(new Pattern('(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$'), '\1\2sis');
yield new Transformation(new Pattern('(tax)a$'), '\1on');
yield new Transformation(new Pattern('(c)riteria$'), '\1riterion');
yield new Transformation(new Pattern('([ti])a(?<!regatta)$'), '\1um');
yield new Transformation(new Pattern('(p)eople$'), '\1\2erson');
yield new Transformation(new Pattern('(m)en$'), '\1an');
yield new Transformation(new Pattern('(c)hildren$'), '\1\2hild');
yield new Transformation(new Pattern('(f)eet$'), '\1oot');
yield new Transformation(new Pattern('(n)ews$'), '\1\2ews');
yield new Transformation(new Pattern('eaus$'), 'eau');
yield new Transformation(new Pattern('^tights$'), 'tights');
yield new Transformation(new Pattern('^shorts$'), 'shorts');
yield new Transformation(new Pattern('s$'), '');
}
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatuses');
yield new Transformation(new Pattern('(quiz)$'), '\1zes');
yield new Transformation(new Pattern('^(ox)$'), '\1\2en');
yield new Transformation(new Pattern('([m|l])ouse$'), '\1ice');
yield new Transformation(new Pattern('(matr|vert|ind)(ix|ex)$'), '\1ices');
yield new Transformation(new Pattern('(x|ch|ss|sh)$'), '\1es');
yield new Transformation(new Pattern('([^aeiouy]|qu)y$'), '\1ies');
yield new Transformation(new Pattern('(hive|gulf)$'), '\1s');
yield new Transformation(new Pattern('(?:([^f])fe|([lr])f)$'), '\1\2ves');
yield new Transformation(new Pattern('sis$'), 'ses');
yield new Transformation(new Pattern('([ti])um$'), '\1a');
yield new Transformation(new Pattern('(tax)on$'), '\1a');
yield new Transformation(new Pattern('(c)riterion$'), '\1riteria');
yield new Transformation(new Pattern('(p)erson$'), '\1eople');
yield new Transformation(new Pattern('(m)an$'), '\1en');
yield new Transformation(new Pattern('(c)hild$'), '\1hildren');
yield new Transformation(new Pattern('(f)oot$'), '\1eet');
yield new Transformation(new Pattern('(buffal|her|potat|tomat|volcan)o$'), '\1\2oes');
yield new Transformation(new Pattern('(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$'), '\1i');
yield new Transformation(new Pattern('us$'), 'uses');
yield new Transformation(new Pattern('(alias)$'), '\1es');
yield new Transformation(new Pattern('(analys|ax|cris|test|thes)is$'), '\1es');
yield new Transformation(new Pattern('s$'), 's');
yield new Transformation(new Pattern('^$'), '');
yield new Transformation(new Pattern('$'), 's');
}
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('abuse'), new Word('abuses'));
yield new Substitution(new Word('alga'), new Word('algae'));
yield new Substitution(new Word('atlas'), new Word('atlases'));
yield new Substitution(new Word('avalanche'), new Word('avalanches'));
yield new Substitution(new Word('axis'), new Word('axes'));
yield new Substitution(new Word('axe'), new Word('axes'));
yield new Substitution(new Word('beef'), new Word('beefs'));
yield new Substitution(new Word('blouse'), new Word('blouses'));
yield new Substitution(new Word('brother'), new Word('brothers'));
yield new Substitution(new Word('brownie'), new Word('brownies'));
yield new Substitution(new Word('cache'), new Word('caches'));
yield new Substitution(new Word('cafe'), new Word('cafes'));
yield new Substitution(new Word('canvas'), new Word('canvases'));
yield new Substitution(new Word('cave'), new Word('caves'));
yield new Substitution(new Word('chateau'), new Word('chateaux'));
yield new Substitution(new Word('child'), new Word('children'));
yield new Substitution(new Word('cookie'), new Word('cookies'));
yield new Substitution(new Word('corpus'), new Word('corpuses'));
yield new Substitution(new Word('cow'), new Word('cows'));
yield new Substitution(new Word('criterion'), new Word('criteria'));
yield new Substitution(new Word('curriculum'), new Word('curricula'));
yield new Substitution(new Word('curve'), new Word('curves'));
yield new Substitution(new Word('demo'), new Word('demos'));
yield new Substitution(new Word('die'), new Word('dice'));
yield new Substitution(new Word('domino'), new Word('dominoes'));
yield new Substitution(new Word('echo'), new Word('echoes'));
yield new Substitution(new Word('emphasis'), new Word('emphases'));
yield new Substitution(new Word('epoch'), new Word('epochs'));
yield new Substitution(new Word('foe'), new Word('foes'));
yield new Substitution(new Word('foot'), new Word('feet'));
yield new Substitution(new Word('fungus'), new Word('fungi'));
yield new Substitution(new Word('ganglion'), new Word('ganglions'));
yield new Substitution(new Word('gas'), new Word('gases'));
yield new Substitution(new Word('genie'), new Word('genies'));
yield new Substitution(new Word('genus'), new Word('genera'));
yield new Substitution(new Word('goose'), new Word('geese'));
yield new Substitution(new Word('graffito'), new Word('graffiti'));
yield new Substitution(new Word('grave'), new Word('graves'));
yield new Substitution(new Word('hippopotamus'), new Word('hippopotami'));
yield new Substitution(new Word('hoax'), new Word('hoaxes'));
yield new Substitution(new Word('hoof'), new Word('hoofs'));
yield new Substitution(new Word('human'), new Word('humans'));
yield new Substitution(new Word('iris'), new Word('irises'));
yield new Substitution(new Word('larva'), new Word('larvae'));
yield new Substitution(new Word('leaf'), new Word('leaves'));
yield new Substitution(new Word('lens'), new Word('lenses'));
yield new Substitution(new Word('loaf'), new Word('loaves'));
yield new Substitution(new Word('man'), new Word('men'));
yield new Substitution(new Word('medium'), new Word('media'));
yield new Substitution(new Word('memorandum'), new Word('memoranda'));
yield new Substitution(new Word('money'), new Word('monies'));
yield new Substitution(new Word('mongoose'), new Word('mongooses'));
yield new Substitution(new Word('motto'), new Word('mottoes'));
yield new Substitution(new Word('move'), new Word('moves'));
yield new Substitution(new Word('mythos'), new Word('mythoi'));
yield new Substitution(new Word('neurosis'), new Word('neuroses'));
yield new Substitution(new Word('niche'), new Word('niches'));
yield new Substitution(new Word('niveau'), new Word('niveaux'));
yield new Substitution(new Word('nucleus'), new Word('nuclei'));
yield new Substitution(new Word('numen'), new Word('numina'));
yield new Substitution(new Word('nursery'), new Word('nurseries'));
yield new Substitution(new Word('oasis'), new Word('oases'));
yield new Substitution(new Word('occiput'), new Word('occiputs'));
yield new Substitution(new Word('octopus'), new Word('octopuses'));
yield new Substitution(new Word('opus'), new Word('opuses'));
yield new Substitution(new Word('ox'), new Word('oxen'));
yield new Substitution(new Word('passerby'), new Word('passersby'));
yield new Substitution(new Word('penis'), new Word('penises'));
yield new Substitution(new Word('person'), new Word('people'));
yield new Substitution(new Word('plateau'), new Word('plateaux'));
yield new Substitution(new Word('runner-up'), new Word('runners-up'));
yield new Substitution(new Word('safe'), new Word('safes'));
yield new Substitution(new Word('save'), new Word('saves'));
yield new Substitution(new Word('sex'), new Word('sexes'));
yield new Substitution(new Word('sieve'), new Word('sieves'));
yield new Substitution(new Word('soliloquy'), new Word('soliloquies'));
yield new Substitution(new Word('son-in-law'), new Word('sons-in-law'));
yield new Substitution(new Word('stadium'), new Word('stadiums'));
yield new Substitution(new Word('syllabus'), new Word('syllabi'));
yield new Substitution(new Word('testis'), new Word('testes'));
yield new Substitution(new Word('thief'), new Word('thieves'));
yield new Substitution(new Word('tooth'), new Word('teeth'));
yield new Substitution(new Word('tornado'), new Word('tornadoes'));
yield new Substitution(new Word('trilby'), new Word('trilbys'));
yield new Substitution(new Word('turf'), new Word('turfs'));
yield new Substitution(new Word('valve'), new Word('valves'));
yield new Substitution(new Word('volcano'), new Word('volcanoes'));
yield new Substitution(new Word('wave'), new Word('waves'));
yield new Substitution(new Word('zombie'), new Word('zombies'));
}
}

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\English;
use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;
final class InflectorFactory extends GenericLanguageInflectorFactory
{
protected function getSingularRuleset(): Ruleset
{
return Rules::getSingularRuleset();
}
protected function getPluralRuleset(): Ruleset
{
return Rules::getPluralRuleset();
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\English;
use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;
final class Rules
{
public static function getSingularRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getSingular()),
new Patterns(...Uninflected::getSingular()),
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
);
}
public static function getPluralRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getPlural()),
new Patterns(...Uninflected::getPlural()),
new Substitutions(...Inflectible::getIrregular())
);
}
}

View File

@@ -1,189 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\English;
use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
yield new Pattern('.*ss');
yield new Pattern('clothes');
yield new Pattern('data');
yield new Pattern('fascia');
yield new Pattern('fuchsia');
yield new Pattern('galleria');
yield new Pattern('mafia');
yield new Pattern('militia');
yield new Pattern('pants');
yield new Pattern('petunia');
yield new Pattern('sepia');
yield new Pattern('trivia');
yield new Pattern('utopia');
}
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
yield new Pattern('people');
yield new Pattern('trivia');
yield new Pattern('\w+ware$');
yield new Pattern('media');
}
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('\w+media');
yield new Pattern('advice');
yield new Pattern('aircraft');
yield new Pattern('amoyese');
yield new Pattern('art');
yield new Pattern('audio');
yield new Pattern('baggage');
yield new Pattern('bison');
yield new Pattern('borghese');
yield new Pattern('bream');
yield new Pattern('breeches');
yield new Pattern('britches');
yield new Pattern('buffalo');
yield new Pattern('butter');
yield new Pattern('cantus');
yield new Pattern('carp');
yield new Pattern('cattle');
yield new Pattern('chassis');
yield new Pattern('clippers');
yield new Pattern('clothing');
yield new Pattern('coal');
yield new Pattern('cod');
yield new Pattern('coitus');
yield new Pattern('compensation');
yield new Pattern('congoese');
yield new Pattern('contretemps');
yield new Pattern('coreopsis');
yield new Pattern('corps');
yield new Pattern('cotton');
yield new Pattern('data');
yield new Pattern('debris');
yield new Pattern('deer');
yield new Pattern('diabetes');
yield new Pattern('djinn');
yield new Pattern('education');
yield new Pattern('eland');
yield new Pattern('elk');
yield new Pattern('emoji');
yield new Pattern('equipment');
yield new Pattern('evidence');
yield new Pattern('faroese');
yield new Pattern('feedback');
yield new Pattern('fish');
yield new Pattern('flounder');
yield new Pattern('flour');
yield new Pattern('foochowese');
yield new Pattern('food');
yield new Pattern('furniture');
yield new Pattern('gallows');
yield new Pattern('genevese');
yield new Pattern('genoese');
yield new Pattern('gilbertese');
yield new Pattern('gold');
yield new Pattern('headquarters');
yield new Pattern('herpes');
yield new Pattern('hijinks');
yield new Pattern('homework');
yield new Pattern('hottentotese');
yield new Pattern('impatience');
yield new Pattern('information');
yield new Pattern('innings');
yield new Pattern('jackanapes');
yield new Pattern('jeans');
yield new Pattern('jedi');
yield new Pattern('kin');
yield new Pattern('kiplingese');
yield new Pattern('knowledge');
yield new Pattern('kongoese');
yield new Pattern('leather');
yield new Pattern('love');
yield new Pattern('lucchese');
yield new Pattern('luggage');
yield new Pattern('mackerel');
yield new Pattern('Maltese');
yield new Pattern('management');
yield new Pattern('metadata');
yield new Pattern('mews');
yield new Pattern('money');
yield new Pattern('moose');
yield new Pattern('mumps');
yield new Pattern('music');
yield new Pattern('nankingese');
yield new Pattern('news');
yield new Pattern('nexus');
yield new Pattern('niasese');
yield new Pattern('nutrition');
yield new Pattern('offspring');
yield new Pattern('oil');
yield new Pattern('patience');
yield new Pattern('pekingese');
yield new Pattern('piedmontese');
yield new Pattern('pincers');
yield new Pattern('pistoiese');
yield new Pattern('plankton');
yield new Pattern('pliers');
yield new Pattern('pokemon');
yield new Pattern('police');
yield new Pattern('polish');
yield new Pattern('portuguese');
yield new Pattern('proceedings');
yield new Pattern('progress');
yield new Pattern('rabies');
yield new Pattern('rain');
yield new Pattern('research');
yield new Pattern('rhinoceros');
yield new Pattern('rice');
yield new Pattern('salmon');
yield new Pattern('sand');
yield new Pattern('sarawakese');
yield new Pattern('scissors');
yield new Pattern('sea[- ]bass');
yield new Pattern('series');
yield new Pattern('shavese');
yield new Pattern('shears');
yield new Pattern('sheep');
yield new Pattern('siemens');
yield new Pattern('silk');
yield new Pattern('sms');
yield new Pattern('soap');
yield new Pattern('social media');
yield new Pattern('spam');
yield new Pattern('species');
yield new Pattern('staff');
yield new Pattern('sugar');
yield new Pattern('swine');
yield new Pattern('talent');
yield new Pattern('toothpaste');
yield new Pattern('traffic');
yield new Pattern('travel');
yield new Pattern('trousers');
yield new Pattern('trout');
yield new Pattern('tuna');
yield new Pattern('us');
yield new Pattern('vermontese');
yield new Pattern('vinegar');
yield new Pattern('weather');
yield new Pattern('wenchowese');
yield new Pattern('wheat');
yield new Pattern('whiting');
yield new Pattern('wildebeest');
yield new Pattern('wood');
yield new Pattern('wool');
yield new Pattern('yengeese');
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Esperanto;
use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('oj$'), 'o');
}
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('o$'), 'oj');
}
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word(''), new Word(''));
}
}

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Esperanto;
use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;
final class InflectorFactory extends GenericLanguageInflectorFactory
{
protected function getSingularRuleset(): Ruleset
{
return Rules::getSingularRuleset();
}
protected function getPluralRuleset(): Ruleset
{
return Rules::getPluralRuleset();
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Esperanto;
use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;
final class Rules
{
public static function getSingularRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getSingular()),
new Patterns(...Uninflected::getSingular()),
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
);
}
public static function getPluralRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getPlural()),
new Patterns(...Uninflected::getPlural()),
new Substitutions(...Inflectible::getIrregular())
);
}
}

View File

@@ -1,28 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Esperanto;
use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('');
}
}

View File

@@ -1,44 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\French;
use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)aux$/'), '\1ail');
yield new Transformation(new Pattern('/ails$/'), 'ail');
yield new Transformation(new Pattern('/(journ|chev|loc)aux$/'), '\1al');
yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)x$/'), '\1');
yield new Transformation(new Pattern('/s$/'), '');
}
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/(s|x|z)$/'), '\1');
yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)ail$/'), '\1aux');
yield new Transformation(new Pattern('/ail$/'), 'ails');
yield new Transformation(new Pattern('/(chacal|carnaval|festival|récital)$/'), '\1s');
yield new Transformation(new Pattern('/al$/'), 'aux');
yield new Transformation(new Pattern('/(bleu|émeu|landau|pneu|sarrau)$/'), '\1s');
yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|lieu|pou|au|eu|eau)$/'), '\1x');
yield new Transformation(new Pattern('/$/'), 's');
}
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('monsieur'), new Word('messieurs'));
yield new Substitution(new Word('madame'), new Word('mesdames'));
yield new Substitution(new Word('mademoiselle'), new Word('mesdemoiselles'));
}
}

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\French;
use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;
final class InflectorFactory extends GenericLanguageInflectorFactory
{
protected function getSingularRuleset(): Ruleset
{
return Rules::getSingularRuleset();
}
protected function getPluralRuleset(): Ruleset
{
return Rules::getPluralRuleset();
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\French;
use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;
final class Rules
{
public static function getSingularRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getSingular()),
new Patterns(...Uninflected::getSingular()),
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
);
}
public static function getPluralRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getPlural()),
new Patterns(...Uninflected::getPlural()),
new Substitutions(...Inflectible::getIrregular())
);
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\French;
use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
yield new Pattern('bois');
yield new Pattern('mas');
}
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('');
}
}

View File

@@ -1,218 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Italian;
use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/** @return iterable<Transformation> */
public static function getSingular(): iterable
{
// Reverse of -sce → -scia (fasce → fascia)
yield new Transformation(new Pattern('([aeiou])sce$'), '\\1scia');
// Reverse of -cie → -cia (farmacia → farmacie)
yield new Transformation(new Pattern('cie$'), 'cia');
// Reverse of -gie → -gia (bugia → bugie)
yield new Transformation(new Pattern('gie$'), 'gia');
// Reverse of -ce → -cia (arance → arancia)
yield new Transformation(new Pattern('([^aeiou])ce$'), '\1cia');
// Reverse of -ge → -gia (valige → valigia)
yield new Transformation(new Pattern('([^aeiou])ge$'), '\1gia');
// Reverse of -chi → -co (bachi → baco)
yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])chi$'), '\1co');
// Reverse of -ghi → -go (laghi → lago)
yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])ghi$'), '\1go');
// Reverse of -ci → -co (medici → medico)
yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])ci$'), '\1co');
// Reverse of -gi → -go (psicologi → psicologo)
yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])gi$'), '\1go');
// Reverse of -i → -io (zii → zio, negozi → negozio)
// This is more complex due to Italian's stress patterns, but we'll handle the basic case
yield new Transformation(new Pattern('([^aeiou])i$'), '\1io');
// Handle words that end with -i but should go to -co/-go (amici → amico, not amice)
yield new Transformation(new Pattern('([^aeiou])ci$'), '\1co');
yield new Transformation(new Pattern('([^aeiou])gi$'), '\1go');
// Reverse of -a → -e
yield new Transformation(new Pattern('e$'), 'a');
// Reverse of -e → -i
yield new Transformation(new Pattern('i$'), 'e');
// Reverse of -o → -i
yield new Transformation(new Pattern('i$'), 'o');
}
/** @return iterable<Transformation> */
public static function getPlural(): iterable
{
// Words ending in -scia without stress on 'i' become -sce (e.g. fascia → fasce)
yield new Transformation(new Pattern('([aeiou])scia$'), '\\1sce');
// Words ending in -cia/gia with stress on 'i' keep the 'i' in plural
yield new Transformation(new Pattern('cia$'), 'cie'); // e.g. farmacia → farmacie
yield new Transformation(new Pattern('gia$'), 'gie'); // e.g. bugia → bugie
// Words ending in -cia/gia without stress on 'i' lose the 'i' in plural
yield new Transformation(new Pattern('([^aeiou])cia$'), '\\1ce'); // e.g. arancia → arance
yield new Transformation(new Pattern('([^aeiou])gia$'), '\\1ge'); // e.g. valigia → valige
// Words ending in -co/-go with stress on 'o' become -chi/-ghi
yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])co$'), '\\1chi'); // e.g. baco → bachi
yield new Transformation(new Pattern('([bcdfghjklmnpqrstvwxyz][aeiou])go$'), '\\1ghi'); // e.g. lago → laghi
// Words ending in -co/-go with stress on the penultimate syllable become -ci/-gi
yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])co$'), '\\1ci'); // e.g. medico → medici
yield new Transformation(new Pattern('([aeiou][bcdfghjklmnpqrstvwxyz])go$'), '\\1gi'); // e.g. psicologo → psicologi
// Words ending in -io with stress on 'i' keep the 'i' in plural
yield new Transformation(new Pattern('([^aeiou])io$'), '\\1i'); // e.g. zio → zii
// Words ending in -io with stress on 'o' lose the 'i' in plural
yield new Transformation(new Pattern('([aeiou])io$'), '\\1i'); // e.g. negozio → negozi
// Standard ending rules
yield new Transformation(new Pattern('a$'), 'e'); // -a → -e
yield new Transformation(new Pattern('e$'), 'i'); // -e → -i
yield new Transformation(new Pattern('o$'), 'i'); // -o → -i
}
/** @return iterable<Substitution> */
public static function getIrregular(): iterable
{
// Irregular substitutions (singular => plural)
$irregulars = [
'ala' => 'ali',
'albergo' => 'alberghi',
'amica' => 'amiche',
'amico' => 'amici',
'ampio' => 'ampi',
'arancia' => 'arance',
'arma' => 'armi',
'asparago' => 'asparagi',
'banca' => 'banche',
'belga' => 'belgi',
'braccio' => 'braccia',
'budello' => 'budella',
'bue' => 'buoi',
'caccia' => 'cacce',
'calcagno' => 'calcagna',
'camicia' => 'camicie',
'cane' => 'cani',
'capitale' => 'capitali',
'carcere' => 'carceri',
'casa' => 'case',
'cavaliere' => 'cavalieri',
'centinaio' => 'centinaia',
'cerchio' => 'cerchia',
'cervello' => 'cervella',
'chiave' => 'chiavi',
'chirurgo' => 'chirurgi',
'ciglio' => 'ciglia',
'città' => 'città',
'corno' => 'corna',
'corpo' => 'corpi',
'crisi' => 'crisi',
'dente' => 'denti',
'dio' => 'dei',
'dito' => 'dita',
'dottore' => 'dottori',
'fiore' => 'fiori',
'fratello' => 'fratelli',
'fuoco' => 'fuochi',
'gamba' => 'gambe',
'ginocchio' => 'ginocchia',
'gioco' => 'giochi',
'giornale' => 'giornali',
'giraffa' => 'giraffe',
'labbro' => 'labbra',
'lenzuolo' => 'lenzuola',
'libro' => 'libri',
'madre' => 'madri',
'maestro' => 'maestri',
'magico' => 'magici',
'mago' => 'maghi',
'maniaco' => 'maniaci',
'manico' => 'manici',
'mano' => 'mani',
'medico' => 'medici',
'membro' => 'membri',
'metropoli' => 'metropoli',
'migliaio' => 'migliaia',
'miglio' => 'miglia',
'mille' => 'mila',
'mio' => 'miei',
'moglie' => 'mogli',
'mosaico' => 'mosaici',
'muro' => 'muri',
'nemico' => 'nemici',
'nome' => 'nomi',
'occhio' => 'occhi',
'orecchio' => 'orecchi',
'osso' => 'ossa',
'paio' => 'paia',
'pane' => 'pani',
'papa' => 'papi',
'pasta' => 'paste',
'penna' => 'penne',
'pesce' => 'pesci',
'piede' => 'piedi',
'pittore' => 'pittori',
'poeta' => 'poeti',
'porco' => 'porci',
'porto' => 'porti',
'problema' => 'problemi',
'ragazzo' => 'ragazzi',
're' => 're',
'rene' => 'reni',
'riso' => 'risa',
'rosa' => 'rosa',
'sale' => 'sali',
'sarto' => 'sarti',
'scuola' => 'scuole',
'serie' => 'serie',
'serramento' => 'serramenta',
'sorella' => 'sorelle',
'specie' => 'specie',
'staio' => 'staia',
'stazione' => 'stazioni',
'strido' => 'strida',
'strillo' => 'strilla',
'studio' => 'studi',
'suo' => 'suoi',
'superficie' => 'superfici',
'tavolo' => 'tavoli',
'tempio' => 'templi',
'treno' => 'treni',
'tuo' => 'tuoi',
'uomo' => 'uomini',
'uovo' => 'uova',
'urlo' => 'urla',
'valigia' => 'valigie',
'vestigio' => 'vestigia',
'vino' => 'vini',
'viola' => 'viola',
'zio' => 'zii',
];
foreach ($irregulars as $singular => $plural) {
yield new Substitution(new Word($singular), new Word($plural));
}
}
}

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Italian;
use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;
final class InflectorFactory extends GenericLanguageInflectorFactory
{
protected function getSingularRuleset(): Ruleset
{
return Rules::getSingularRuleset();
}
protected function getPluralRuleset(): Ruleset
{
return Rules::getPluralRuleset();
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Italian;
use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;
final class Rules
{
public static function getSingularRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getSingular()),
new Patterns(...Uninflected::getSingular()),
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
);
}
public static function getPluralRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getPlural()),
new Patterns(...Uninflected::getPlural()),
new Substitutions(...Inflectible::getIrregular())
);
}
}

View File

@@ -1,80 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Italian;
use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/** @return iterable<Pattern> */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/** @return iterable<Pattern> */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/** @return iterable<Pattern> */
private static function getDefault(): iterable
{
// Invariable words (same form in singular and plural)
$invariables = [
'alpaca',
'auto',
'bar',
'blu',
'boia',
'boomerang',
'brindisi',
'campus',
'computer',
'crisi',
'crocevia',
'dopocena',
'film',
'foto',
'fuchsia',
'gnu',
'gorilla',
'gru',
'iguana',
'kamikaze',
'karaoke',
'koala',
'lama',
'menu',
'metropoli',
'moto',
'opossum',
'panda',
'quiz',
'radio',
're',
'scacciapensieri',
'serie',
'smartphone',
'sosia',
'sottoscala',
'specie',
'sport',
'tablet',
'taxi',
'vaglia',
'virtù',
'virus',
'yogurt',
'foto',
'fuchsia',
];
foreach ($invariables as $word) {
yield new Pattern($word);
}
}
}

View File

@@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/re$/i'), 'r');
yield new Transformation(new Pattern('/er$/i'), '');
}
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/e$/i'), 'er');
yield new Transformation(new Pattern('/r$/i'), 're');
yield new Transformation(new Pattern('/$/'), 'er');
}
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('konto'), new Word('konti'));
}
}

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;
final class InflectorFactory extends GenericLanguageInflectorFactory
{
protected function getSingularRuleset(): Ruleset
{
return Rules::getSingularRuleset();
}
protected function getPluralRuleset(): Ruleset
{
return Rules::getPluralRuleset();
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;
final class Rules
{
public static function getSingularRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getSingular()),
new Patterns(...Uninflected::getSingular()),
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
);
}
public static function getPluralRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getPlural()),
new Patterns(...Uninflected::getPlural()),
new Substitutions(...Inflectible::getIrregular())
);
}
}

View File

@@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\NorwegianBokmal;
use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('barn');
yield new Pattern('fjell');
yield new Pattern('hus');
}
}

View File

@@ -1,42 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules;
use function preg_match;
final class Pattern
{
/** @var string */
private $pattern;
/** @var string */
private $regex;
public function __construct(string $pattern)
{
$this->pattern = $pattern;
if (isset($this->pattern[0]) && $this->pattern[0] === '/') {
$this->regex = $this->pattern;
} else {
$this->regex = '/' . $this->pattern . '/i';
}
}
public function getPattern(): string
{
return $this->pattern;
}
public function getRegex(): string
{
return $this->regex;
}
public function matches(string $word): bool
{
return preg_match($this->getRegex(), $word) === 1;
}
}

View File

@@ -1,29 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules;
use function array_map;
use function implode;
use function preg_match;
class Patterns
{
/** @var string */
private $regex;
public function __construct(Pattern ...$patterns)
{
$patterns = array_map(static function (Pattern $pattern): string {
return $pattern->getPattern();
}, $patterns);
$this->regex = '/^(?:' . implode('|', $patterns) . ')$/i';
}
public function matches(string $word): bool
{
return preg_match($this->regex, $word, $regs) === 1;
}
}

View File

@@ -1,98 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Portuguese;
use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/^(g|)ases$/i'), '\1ás');
yield new Transformation(new Pattern('/(japon|escoc|ingl|dinamarqu|fregu|portugu)eses$/i'), '\1ês');
yield new Transformation(new Pattern('/(ae|ao|oe)s$/'), 'ao');
yield new Transformation(new Pattern('/(ãe|ão|õe)s$/'), 'ão');
yield new Transformation(new Pattern('/^(.*[^s]s)es$/i'), '\1');
yield new Transformation(new Pattern('/sses$/i'), 'sse');
yield new Transformation(new Pattern('/ns$/i'), 'm');
yield new Transformation(new Pattern('/(r|t|f|v)is$/i'), '\1il');
yield new Transformation(new Pattern('/uis$/i'), 'ul');
yield new Transformation(new Pattern('/ois$/i'), 'ol');
yield new Transformation(new Pattern('/eis$/i'), 'ei');
yield new Transformation(new Pattern('/éis$/i'), 'el');
yield new Transformation(new Pattern('/([^p])ais$/i'), '\1al');
yield new Transformation(new Pattern('/(r|z)es$/i'), '\1');
yield new Transformation(new Pattern('/^(á|gá)s$/i'), '\1s');
yield new Transformation(new Pattern('/([^ê])s$/i'), '\1');
}
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/^(alem|c|p)ao$/i'), '\1aes');
yield new Transformation(new Pattern('/^(irm|m)ao$/i'), '\1aos');
yield new Transformation(new Pattern('/ao$/i'), 'oes');
yield new Transformation(new Pattern('/^(alem|c|p)ão$/i'), '\1ães');
yield new Transformation(new Pattern('/^(irm|m)ão$/i'), '\1ãos');
yield new Transformation(new Pattern('/ão$/i'), 'ões');
yield new Transformation(new Pattern('/^(|g)ás$/i'), '\1ases');
yield new Transformation(new Pattern('/^(japon|escoc|ingl|dinamarqu|fregu|portugu)ês$/i'), '\1eses');
yield new Transformation(new Pattern('/m$/i'), 'ns');
yield new Transformation(new Pattern('/([^aeou])il$/i'), '\1is');
yield new Transformation(new Pattern('/ul$/i'), 'uis');
yield new Transformation(new Pattern('/ol$/i'), 'ois');
yield new Transformation(new Pattern('/el$/i'), 'eis');
yield new Transformation(new Pattern('/al$/i'), 'ais');
yield new Transformation(new Pattern('/(z|r)$/i'), '\1es');
yield new Transformation(new Pattern('/(s)$/i'), '\1');
yield new Transformation(new Pattern('/$/'), 's');
}
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('abdomen'), new Word('abdomens'));
yield new Substitution(new Word('alemão'), new Word('alemães'));
yield new Substitution(new Word('artesã'), new Word('artesãos'));
yield new Substitution(new Word('álcool'), new Word('álcoois'));
yield new Substitution(new Word('árvore'), new Word('árvores'));
yield new Substitution(new Word('bencão'), new Word('bencãos'));
yield new Substitution(new Word('cão'), new Word('cães'));
yield new Substitution(new Word('campus'), new Word('campi'));
yield new Substitution(new Word('cadáver'), new Word('cadáveres'));
yield new Substitution(new Word('capelão'), new Word('capelães'));
yield new Substitution(new Word('capitão'), new Word('capitães'));
yield new Substitution(new Word('chão'), new Word('chãos'));
yield new Substitution(new Word('charlatão'), new Word('charlatães'));
yield new Substitution(new Word('cidadão'), new Word('cidadãos'));
yield new Substitution(new Word('consul'), new Word('consules'));
yield new Substitution(new Word('cristão'), new Word('cristãos'));
yield new Substitution(new Word('difícil'), new Word('difíceis'));
yield new Substitution(new Word('email'), new Word('emails'));
yield new Substitution(new Word('escrivão'), new Word('escrivães'));
yield new Substitution(new Word('fóssil'), new Word('fósseis'));
yield new Substitution(new Word('gás'), new Word('gases'));
yield new Substitution(new Word('germens'), new Word('germen'));
yield new Substitution(new Word('grão'), new Word('grãos'));
yield new Substitution(new Word('hífen'), new Word('hífens'));
yield new Substitution(new Word('irmão'), new Word('irmãos'));
yield new Substitution(new Word('liquens'), new Word('liquen'));
yield new Substitution(new Word('mal'), new Word('males'));
yield new Substitution(new Word('mão'), new Word('mãos'));
yield new Substitution(new Word('orfão'), new Word('orfãos'));
yield new Substitution(new Word('país'), new Word('países'));
yield new Substitution(new Word('pai'), new Word('pais'));
yield new Substitution(new Word('pão'), new Word('pães'));
yield new Substitution(new Word('projétil'), new Word('projéteis'));
yield new Substitution(new Word('réptil'), new Word('répteis'));
yield new Substitution(new Word('sacristão'), new Word('sacristães'));
yield new Substitution(new Word('sotão'), new Word('sotãos'));
yield new Substitution(new Word('tabelião'), new Word('tabeliães'));
}
}

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Portuguese;
use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;
final class InflectorFactory extends GenericLanguageInflectorFactory
{
protected function getSingularRuleset(): Ruleset
{
return Rules::getSingularRuleset();
}
protected function getPluralRuleset(): Ruleset
{
return Rules::getPluralRuleset();
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Portuguese;
use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;
final class Rules
{
public static function getSingularRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getSingular()),
new Patterns(...Uninflected::getSingular()),
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
);
}
public static function getPluralRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getPlural()),
new Patterns(...Uninflected::getPlural()),
new Substitutions(...Inflectible::getIrregular())
);
}
}

View File

@@ -1,32 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Portuguese;
use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('tórax');
yield new Pattern('tênis');
yield new Pattern('ônibus');
yield new Pattern('lápis');
yield new Pattern('fênix');
}
}

View File

@@ -1,39 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules;
class Ruleset
{
/** @var Transformations */
private $regular;
/** @var Patterns */
private $uninflected;
/** @var Substitutions */
private $irregular;
public function __construct(Transformations $regular, Patterns $uninflected, Substitutions $irregular)
{
$this->regular = $regular;
$this->uninflected = $uninflected;
$this->irregular = $irregular;
}
public function getRegular(): Transformations
{
return $this->regular;
}
public function getUninflected(): Patterns
{
return $this->uninflected;
}
public function getIrregular(): Substitutions
{
return $this->irregular;
}
}

View File

@@ -1,47 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Spanish;
use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/ereses$/'), 'erés');
yield new Transformation(new Pattern('/iones$/'), 'ión');
yield new Transformation(new Pattern('/ces$/'), 'z');
yield new Transformation(new Pattern('/es$/'), '');
yield new Transformation(new Pattern('/s$/'), '');
}
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/ú([sn])$/i'), 'u\1es');
yield new Transformation(new Pattern('/ó([sn])$/i'), 'o\1es');
yield new Transformation(new Pattern('/í([sn])$/i'), 'i\1es');
yield new Transformation(new Pattern('/é([sn])$/i'), 'e\1es');
yield new Transformation(new Pattern('/á([sn])$/i'), 'a\1es');
yield new Transformation(new Pattern('/z$/i'), 'ces');
yield new Transformation(new Pattern('/([aeiou]s)$/i'), '\1');
yield new Transformation(new Pattern('/([^aeéiou])$/i'), '\1es');
yield new Transformation(new Pattern('/$/'), 's');
}
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('el'), new Word('los'));
yield new Substitution(new Word('papá'), new Word('papás'));
yield new Substitution(new Word('mamá'), new Word('mamás'));
yield new Substitution(new Word('sofá'), new Word('sofás'));
yield new Substitution(new Word('mes'), new Word('meses'));
}
}

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Spanish;
use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;
final class InflectorFactory extends GenericLanguageInflectorFactory
{
protected function getSingularRuleset(): Ruleset
{
return Rules::getSingularRuleset();
}
protected function getPluralRuleset(): Ruleset
{
return Rules::getPluralRuleset();
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Spanish;
use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;
final class Rules
{
public static function getSingularRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getSingular()),
new Patterns(...Uninflected::getSingular()),
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
);
}
public static function getPluralRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getPlural()),
new Patterns(...Uninflected::getPlural()),
new Substitutions(...Inflectible::getIrregular())
);
}
}

View File

@@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Spanish;
use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('lunes');
yield new Pattern('rompecabezas');
yield new Pattern('crisis');
}
}

View File

@@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules;
final class Substitution
{
/** @var Word */
private $from;
/** @var Word */
private $to;
public function __construct(Word $from, Word $to)
{
$this->from = $from;
$this->to = $to;
}
public function getFrom(): Word
{
return $this->from;
}
public function getTo(): Word
{
return $this->to;
}
}

View File

@@ -1,57 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules;
use Doctrine\Inflector\WordInflector;
use function strtolower;
use function strtoupper;
use function substr;
class Substitutions implements WordInflector
{
/** @var Substitution[] */
private $substitutions;
public function __construct(Substitution ...$substitutions)
{
foreach ($substitutions as $substitution) {
$this->substitutions[$substitution->getFrom()->getWord()] = $substitution;
}
}
public function getFlippedSubstitutions(): Substitutions
{
$substitutions = [];
foreach ($this->substitutions as $substitution) {
$substitutions[] = new Substitution(
$substitution->getTo(),
$substitution->getFrom()
);
}
return new Substitutions(...$substitutions);
}
public function inflect(string $word): string
{
$lowerWord = strtolower($word);
if (isset($this->substitutions[$lowerWord])) {
$firstLetterUppercase = $lowerWord[0] !== $word[0];
$toWord = $this->substitutions[$lowerWord]->getTo()->getWord();
if ($firstLetterUppercase) {
return strtoupper($toWord[0]) . substr($toWord, 1);
}
return $toWord;
}
return $word;
}
}

View File

@@ -1,39 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules;
use Doctrine\Inflector\WordInflector;
use function preg_replace;
final class Transformation implements WordInflector
{
/** @var Pattern */
private $pattern;
/** @var string */
private $replacement;
public function __construct(Pattern $pattern, string $replacement)
{
$this->pattern = $pattern;
$this->replacement = $replacement;
}
public function getPattern(): Pattern
{
return $this->pattern;
}
public function getReplacement(): string
{
return $this->replacement;
}
public function inflect(string $word): string
{
return (string) preg_replace($this->pattern->getRegex(), $this->replacement, $word);
}
}

View File

@@ -1,29 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules;
use Doctrine\Inflector\WordInflector;
class Transformations implements WordInflector
{
/** @var Transformation[] */
private $transformations;
public function __construct(Transformation ...$transformations)
{
$this->transformations = $transformations;
}
public function inflect(string $word): string
{
foreach ($this->transformations as $transformation) {
if ($transformation->getPattern()->matches($word)) {
return $transformation->inflect($word);
}
}
return $word;
}
}

View File

@@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Turkish;
use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;
class Inflectible
{
/** @return Transformation[] */
public static function getSingular(): iterable
{
yield new Transformation(new Pattern('/l[ae]r$/i'), '');
}
/** @return Transformation[] */
public static function getPlural(): iterable
{
yield new Transformation(new Pattern('/([eöiü][^aoıueöiü]{0,6})$/u'), '\1ler');
yield new Transformation(new Pattern('/([aoıu][^aoıueöiü]{0,6})$/u'), '\1lar');
}
/** @return Substitution[] */
public static function getIrregular(): iterable
{
yield new Substitution(new Word('ben'), new Word('biz'));
yield new Substitution(new Word('sen'), new Word('siz'));
yield new Substitution(new Word('o'), new Word('onlar'));
}
}

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Turkish;
use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;
final class InflectorFactory extends GenericLanguageInflectorFactory
{
protected function getSingularRuleset(): Ruleset
{
return Rules::getSingularRuleset();
}
protected function getPluralRuleset(): Ruleset
{
return Rules::getPluralRuleset();
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Turkish;
use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;
final class Rules
{
public static function getSingularRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getSingular()),
new Patterns(...Uninflected::getSingular()),
(new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
);
}
public static function getPluralRuleset(): Ruleset
{
return new Ruleset(
new Transformations(...Inflectible::getPlural()),
new Patterns(...Uninflected::getPlural()),
new Substitutions(...Inflectible::getIrregular())
);
}
}

View File

@@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules\Turkish;
use Doctrine\Inflector\Rules\Pattern;
final class Uninflected
{
/** @return Pattern[] */
public static function getSingular(): iterable
{
yield from self::getDefault();
}
/** @return Pattern[] */
public static function getPlural(): iterable
{
yield from self::getDefault();
}
/** @return Pattern[] */
private static function getDefault(): iterable
{
yield new Pattern('lunes');
yield new Pattern('rompecabezas');
yield new Pattern('crisis');
}
}

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector\Rules;
class Word
{
/** @var string */
private $word;
public function __construct(string $word)
{
$this->word = $word;
}
public function getWord(): string
{
return $this->word;
}
}

View File

@@ -1,56 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector;
use Doctrine\Inflector\Rules\Ruleset;
use function array_merge;
/**
* Inflects based on multiple rulesets.
*
* Rules:
* - If the word matches any uninflected word pattern, it is not inflected
* - The first ruleset that returns a different value for an irregular word wins
* - The first ruleset that returns a different value for a regular word wins
* - If none of the above match, the word is left as-is
*/
class RulesetInflector implements WordInflector
{
/** @var Ruleset[] */
private $rulesets;
public function __construct(Ruleset $ruleset, Ruleset ...$rulesets)
{
$this->rulesets = array_merge([$ruleset], $rulesets);
}
public function inflect(string $word): string
{
if ($word === '') {
return '';
}
foreach ($this->rulesets as $ruleset) {
if ($ruleset->getUninflected()->matches($word)) {
return $word;
}
$inflected = $ruleset->getIrregular()->inflect($word);
if ($inflected !== $word) {
return $inflected;
}
$inflected = $ruleset->getRegular()->inflect($word);
if ($inflected !== $word) {
return $inflected;
}
}
return $word;
}
}

View File

@@ -1,10 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Inflector;
interface WordInflector
{
public function inflect(string $word): string;
}

View File

@@ -5,6 +5,41 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 2.12.3 - 2026-06-23
### Security
- Validate the URI host so `getHost()` matches the URI authority (GHSA-c2w2-prh8-qm98)
## 2.12.2 - 2026-06-23
### Fixed
- Report URI parsing, filtering, and normalization PCRE failures explicitly
- Report HTTP message parser PCRE failures explicitly
- Fail closed when PCRE validation fails for request targets and hosts
## 2.12.1 - 2026-06-18
### Security
- Reject CR/LF in HTTP method, protocol version, and reason phrase (GHSA-vm85-hxw5-5432)
## 2.12.0 - 2026-06-16
### Deprecated
- Deprecated non-finite float values in `Query::build()` that guzzlehttp/psr7 3.0 rejects
- Deprecated non-finite float multipart contents that guzzlehttp/psr7 3.0 rejects
- Deprecated non-string scalar bodies in `Utils::streamFor()`; cast them to a string for 3.0
- Deprecated non-string `Uri::withQueryValues()` values; cast them to a string for 3.0
## 2.11.1 - 2026-06-12
### Fixed
- Fixed non-finite float values emitting coercion warnings on PHP 8.5
## 2.11.0 - 2026-06-02
### Changed

View File

@@ -55,7 +55,7 @@
"psr/http-message": "^1.1 || ^2.0",
"ralouphie/getallheaders": "^3.0",
"symfony/deprecation-contracts": "^2.5 || ^3.0",
"symfony/polyfill-php80": "^1.24"
"symfony/polyfill-php80": "^1.25"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",

View File

@@ -181,7 +181,11 @@ final class Message
$messageParts = preg_split("/\r?\n\r?\n/", $message, 2);
if ($messageParts === false || count($messageParts) !== 2) {
if ($messageParts === false) {
throw new \RuntimeException('Unable to split HTTP message: '.preg_last_error_msg());
}
if (count($messageParts) !== 2) {
throw new \InvalidArgumentException('Invalid message: Missing header delimiter');
}
@@ -189,24 +193,48 @@ final class Message
$rawHeaders .= "\r\n"; // Put back the delimiter we split previously
$headerParts = preg_split("/\r?\n/", $rawHeaders, 2);
if ($headerParts === false || count($headerParts) !== 2) {
if ($headerParts === false) {
throw new \RuntimeException('Unable to split HTTP message headers: '.preg_last_error_msg());
}
if (count($headerParts) !== 2) {
throw new \InvalidArgumentException('Invalid message: Missing status line');
}
[$startLine, $rawHeaders] = $headerParts;
if (preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') {
$versionMatch = preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches);
if ($versionMatch === false) {
throw new \RuntimeException('Unable to parse HTTP start line: '.preg_last_error_msg());
}
if ($versionMatch === 1 && $matches[1] === '1.0') {
// Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0
$rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders);
if ($rawHeaders === null) {
throw new \RuntimeException('Unable to unfold HTTP headers: '.preg_last_error_msg());
}
}
/** @var array[] $headerLines */
$count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER);
if ($count === false) {
throw new \RuntimeException('Unable to parse HTTP headers: '.preg_last_error_msg());
}
// If these aren't the same, then one line didn't match and there's an invalid header.
if ($count !== substr_count($rawHeaders, "\n")) {
// Folding is deprecated, see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4
if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) {
$hasFoldedHeader = preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders);
if ($hasFoldedHeader === false) {
throw new \RuntimeException('Unable to inspect HTTP header folding: '.preg_last_error_msg());
}
if ($hasFoldedHeader === 1) {
throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding');
}
@@ -278,8 +306,18 @@ final class Message
public static function parseRequest(string $message): RequestInterface
{
$data = self::parseMessage($message);
if (strpbrk($data['start-line'], "\r\n") !== false) {
throw new \InvalidArgumentException('Invalid request string');
}
$matches = [];
if (!preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) {
$requestStartLineMatch = preg_match('/^[\S]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches);
if ($requestStartLineMatch === false) {
throw new \RuntimeException('Unable to parse request start line: '.preg_last_error_msg());
}
if ($requestStartLineMatch === 0) {
throw new \InvalidArgumentException('Invalid request string');
}
$parts = explode(' ', $data['start-line'], 3);
@@ -304,10 +342,20 @@ final class Message
public static function parseResponse(string $message): ResponseInterface
{
$data = self::parseMessage($message);
if (strpbrk($data['start-line'], "\r\n") !== false) {
throw new \InvalidArgumentException('Invalid response string');
}
// According to https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2
// the space between status-code and reason-phrase is required. But
// browsers accept responses without space and reason as well.
if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {
$responseStartLineMatch = preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line']);
if ($responseStartLineMatch === false) {
throw new \RuntimeException('Unable to parse response start line: '.preg_last_error_msg());
}
if ($responseStartLineMatch === 0) {
throw new \InvalidArgumentException('Invalid response string: '.$data['start-line']);
}
$parts = explode(' ', $data['start-line'], 3);

View File

@@ -43,6 +43,8 @@ trait MessageTrait
);
}
$this->assertProtocolVersion($version);
if ($this->protocol === $version) {
return $this;
}
@@ -273,6 +275,12 @@ trait MessageTrait
));
}
// Convert non-finite floats explicitly, as implicit coercion of
// NAN emits a warning on PHP 8.5.
if (is_float($value) && !is_finite($value)) {
$value = is_nan($value) ? 'NAN' : ($value > 0 ? 'INF' : '-INF');
}
$trimmed = trim((string) $value, " \t");
$this->assertValue($trimmed);
@@ -301,6 +309,23 @@ trait MessageTrait
}
}
/**
* @param mixed $version
*/
private function assertProtocolVersion($version): void
{
if (is_string($version)) {
$this->assertNoLineSeparators($version, 'Protocol version');
}
}
private function assertNoLineSeparators(string $value, string $field): void
{
if (strpbrk($value, "\r\n") !== false) {
throw new \InvalidArgumentException($field.' must not contain CR or LF characters.');
}
}
/**
* @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2
*

View File

@@ -26,8 +26,9 @@ final class MultipartStream implements StreamInterface
* @param array $elements Array of associative arrays, each containing a
* required "name" key mapping to the form field,
* name, a required "contents" key mapping to any
* non-array value accepted by Utils::streamFor(),
* or an array for nested expansion.
* non-array value accepted by Utils::streamFor()
* (non-string scalar field values are cast to
* string), or an array for nested expansion.
* Optional keys include "headers" (associative
* array of custom headers) and "filename" (string
* to send as the filename in the part).
@@ -124,7 +125,27 @@ final class MultipartStream implements StreamInterface
return;
}
$element['contents'] = Utils::streamFor($element['contents']);
$contents = $element['contents'];
if (is_scalar($contents) && !is_string($contents)) {
// Multipart field values are byte strings on the wire, so finite
// numeric and boolean field values are cast to string here rather
// than tripping streamFor()'s non-string-scalar deprecation. Non-finite
// floats are deprecated and normalized here too, so the deprecation is
// reported against MultipartStream instead of transitively through
// streamFor().
if (is_float($contents) && !is_finite($contents)) {
\trigger_deprecation(
'guzzlehttp/psr7',
'2.12',
'Passing a non-finite float as multipart contents is deprecated; guzzlehttp/psr7 3.0 rejects non-finite floats.'
);
$contents = is_nan($contents) ? 'NAN' : ($contents > 0 ? 'INF' : '-INF');
}
$contents = (string) $contents;
}
$element['contents'] = Utils::streamFor($contents);
if (empty($element['filename'])) {
$uri = $element['contents']->getMetadata('uri');

View File

@@ -96,7 +96,7 @@ final class Query
$k = $encoder((string) $k);
if (!is_array($v)) {
$qs .= $k;
$v = is_bool($v) ? $castBool($v) : $v;
$v = is_bool($v) ? $castBool($v) : self::normalizeNonFiniteFloat($v);
if ($v !== null) {
$qs .= '='.$encoder((string) $v);
}
@@ -104,7 +104,7 @@ final class Query
} else {
foreach ($v as $vv) {
$qs .= $k;
$vv = is_bool($vv) ? $castBool($vv) : $vv;
$vv = is_bool($vv) ? $castBool($vv) : self::normalizeNonFiniteFloat($vv);
if ($vv !== null) {
$qs .= '='.$encoder((string) $vv);
}
@@ -115,4 +115,27 @@ final class Query
return $qs ? (string) substr($qs, 0, -1) : '';
}
/**
* Converts non-finite floats to the strings PHP coerces them to, as
* implicit coercion of NAN emits a warning on PHP 8.5.
*
* @param mixed $value
*
* @return mixed
*/
private static function normalizeNonFiniteFloat($value)
{
if (is_float($value) && !is_finite($value)) {
\trigger_deprecation(
'guzzlehttp/psr7',
'2.12',
'Passing a non-finite float to Query::build() is deprecated; guzzlehttp/psr7 3.0 rejects non-finite floats.'
);
return is_nan($value) ? 'NAN' : ($value > 0 ? 'INF' : '-INF');
}
return $value;
}
}

View File

@@ -40,6 +40,8 @@ class Request implements RequestInterface
string $version = '1.1'
) {
$this->assertMethod($method);
$this->assertProtocolVersion($version);
if (!$uri instanceof UriInterface) {
$uri = new Uri($uri);
}
@@ -78,7 +80,13 @@ class Request implements RequestInterface
public function withRequestTarget($requestTarget): RequestInterface
{
if (preg_match('#\s#', $requestTarget)) {
$hasWhitespace = preg_match('#\s#', $requestTarget);
if ($hasWhitespace === false) {
throw new \RuntimeException('Unable to validate request target: '.preg_last_error_msg());
}
if ($hasWhitespace === 1) {
throw new InvalidArgumentException(
'Invalid request target provided; cannot contain whitespace'
);
@@ -170,6 +178,8 @@ class Request implements RequestInterface
if (!is_string($method) || $method === '') {
throw new InvalidArgumentException('Method must be a non-empty string.');
}
$this->assertNoLineSeparators($method, 'Method');
}
private static function warnOnMethodCasingChange(string $method): void

View File

@@ -99,6 +99,7 @@ class Response implements ResponseInterface
?string $reason = null
) {
$this->assertStatusCodeRange($status);
$this->assertProtocolVersion($version);
$this->statusCode = $status;
@@ -108,11 +109,14 @@ class Response implements ResponseInterface
$this->setHeaders($headers);
if ($reason == '' && isset(self::PHRASES[$this->statusCode])) {
$this->reasonPhrase = self::PHRASES[$this->statusCode];
$reasonPhrase = self::PHRASES[$this->statusCode];
} else {
$this->reasonPhrase = (string) $reason;
$reasonPhrase = (string) $reason;
}
$this->assertNoLineSeparators($reasonPhrase, 'Reason phrase');
$this->reasonPhrase = $reasonPhrase;
$this->protocol = $version;
}
@@ -155,7 +159,9 @@ class Response implements ResponseInterface
if ($reasonPhrase == '' && isset(self::PHRASES[$new->statusCode])) {
$reasonPhrase = self::PHRASES[$new->statusCode];
}
$new->reasonPhrase = (string) $reasonPhrase;
$reasonPhrase = (string) $reasonPhrase;
$this->assertNoLineSeparators($reasonPhrase, 'Reason phrase');
$new->reasonPhrase = $reasonPhrase;
return $new;
}

View File

@@ -68,7 +68,13 @@ final class Rfc7230
private static function isValidHostHeaderHost(string $host): bool
{
if (preg_match('/[\x00-\x20\x7F\/\?#@\\\\]/', $host)) {
$invalidHost = preg_match('/[\x00-\x20\x7F\/\?#@\\\\]/', $host);
if ($invalidHost === false) {
return false;
}
if ($invalidHost === 1) {
return false;
}

View File

@@ -101,10 +101,22 @@ class Uri implements UriInterface, \JsonSerializable
// Preserve bracketed IPv6 literals before encoding, including dotted IPv4 tails.
$prefix = '';
if (preg_match('%^([0-9A-Za-z+.-]+://\[[0-9:.a-fA-F]+\])(.*?)$%', $url, $matches)) {
$ipv6Prefix = preg_match('%\A([0-9A-Za-z+.-]+://\[[^\]\x00-\x20/?#@]+\])(.*)\z%s', $url, $matches);
if ($ipv6Prefix === false) {
return false;
}
if ($ipv6Prefix === 1) {
/** @var array{0:string, 1:string, 2:string} $matches */
$suffix = $matches[2];
if ($suffix !== '' && strpos(':/?#', $suffix[0]) === false) {
return false;
}
$prefix = $matches[1];
$url = $matches[2];
$url = $suffix;
}
/** @var string|null */
@@ -371,12 +383,38 @@ class Uri implements UriInterface, \JsonSerializable
$result = self::getFilteredQueryString($uri, array_keys($keyValueArray));
foreach ($keyValueArray as $key => $value) {
$result[] = self::generateQueryString((string) $key, $value !== null ? (string) $value : null);
$result[] = self::generateQueryString((string) $key, $value !== null ? self::stringifyQueryValue($value) : null);
}
return $uri->withQuery(implode('&', $result));
}
/**
* Stringifies a non-null query value, deprecating non-string values that
* guzzlehttp/psr7 3.0 will reject. Non-finite floats are normalized to the
* strings PHP coerces them to, as implicit coercion of NAN emits a warning
* on PHP 8.5.
*
* @param mixed $value
*/
private static function stringifyQueryValue($value): string
{
if (!is_string($value)) {
\trigger_deprecation(
'guzzlehttp/psr7',
'2.12',
'Passing %s to Uri::withQueryValues() is deprecated; cast it to a string. guzzlehttp/psr7 3.0 will only accept string or null query values.',
\gettype($value)
);
if (is_float($value) && !is_finite($value)) {
return is_nan($value) ? 'NAN' : ($value > 0 ? 'INF' : '-INF');
}
}
return (string) $value;
}
/**
* Creates a URI from a hash of `parse_url` components.
*
@@ -410,7 +448,27 @@ class Uri implements UriInterface, \JsonSerializable
return;
}
if (preg_match('/[\x00-\x20\x7F]/', $host)) {
// Reject control characters and URI authority delimiters so getHost()
// cannot disagree with the on-wire authority.
$invalidHost = preg_match('/[\x00-\x20\x7F\/\?#@\\\\]/', $host);
if ($invalidHost === false) {
throw new \RuntimeException('Unable to validate URI host: '.preg_last_error_msg());
}
if ($invalidHost === 1) {
throw new \InvalidArgumentException(sprintf('Invalid host: "%s"', $host));
}
if (strpos($host, '[') !== false || strpos($host, ']') !== false) {
if ($host[0] !== '[' || substr($host, -1) !== ']') {
throw new \InvalidArgumentException(sprintf('Invalid host: "%s"', $host));
}
return;
}
if (strpos($host, ':') !== false) {
throw new \InvalidArgumentException(sprintf('Invalid host: "%s"', $host));
}
}
@@ -657,10 +715,10 @@ class Uri implements UriInterface, \JsonSerializable
throw new \InvalidArgumentException('User info must be a string');
}
return preg_replace_callback(
return $this->filterComponent(
'/(?:[^%'.Rfc3986::CHAR_UNRESERVED.Rfc3986::CHAR_SUB_DELIMS.']+|%(?![A-Fa-f0-9]{2}))/',
[$this, 'rawurlencodeMatchZero'],
$component
$component,
'Unable to filter URI user info'
);
}
@@ -759,10 +817,10 @@ class Uri implements UriInterface, \JsonSerializable
throw new \InvalidArgumentException('Path must be a string');
}
return preg_replace_callback(
return $this->filterComponent(
'/(?:[^'.Rfc3986::CHAR_UNRESERVED.Rfc3986::CHAR_SUB_DELIMS.'%:@\/]++|%(?![A-Fa-f0-9]{2}))/',
[$this, 'rawurlencodeMatchZero'],
$path
$path,
'Unable to filter URI path'
);
}
@@ -779,13 +837,24 @@ class Uri implements UriInterface, \JsonSerializable
throw new \InvalidArgumentException('Query and fragment must be a string');
}
return preg_replace_callback(
return $this->filterComponent(
'/(?:[^'.Rfc3986::CHAR_UNRESERVED.Rfc3986::CHAR_SUB_DELIMS.'%:@\/\?]++|%(?![A-Fa-f0-9]{2}))/',
[$this, 'rawurlencodeMatchZero'],
$str
$str,
'Unable to filter URI query or fragment'
);
}
private function filterComponent(string $pattern, string $component, string $context): string
{
$filtered = preg_replace_callback($pattern, [$this, 'rawurlencodeMatchZero'], $component);
if ($filtered === null) {
throw new \RuntimeException($context.': '.preg_last_error_msg());
}
return $filtered;
}
private function rawurlencodeMatchZero(array $match): string
{
return rawurlencode($match[0]);

View File

@@ -150,7 +150,13 @@ final class UriNormalizer
}
if ($flags & self::REMOVE_DUPLICATE_SLASHES) {
$uri = $uri->withPath(preg_replace('#//++#', '/', $uri->getPath()));
$path = preg_replace('#//++#', '/', $uri->getPath());
if ($path === null) {
throw new \RuntimeException('Unable to remove duplicate slashes from URI path: '.preg_last_error_msg());
}
$uri = $uri->withPath($path);
}
if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') {
@@ -217,7 +223,7 @@ final class UriNormalizer
$normalized = preg_replace_callback($regex, $callback, $component);
if ($normalized === null) {
throw new \RuntimeException('Unable to normalize URI component percent-encoding');
throw new \RuntimeException('Unable to normalize URI component percent-encoding: '.preg_last_error_msg());
}
return $normalized;

View File

@@ -462,6 +462,9 @@ final class Utils
* in subsequent reads. String inputs are always treated as string bodies,
* even when they name callable functions.
*
* Passing a non-string scalar (`int`, `float`, or `bool`) is deprecated; cast
* it to a string instead. guzzlehttp/psr7 3.0 will reject non-string scalars.
*
* @param resource|string|int|float|bool|StreamInterface|callable|\Iterator|null $resource Entity body data
* @param array{size?: int, metadata?: array} $options Additional options
*
@@ -470,6 +473,22 @@ final class Utils
public static function streamFor($resource = '', array $options = []): StreamInterface
{
if (is_scalar($resource)) {
if (!is_string($resource)) {
\trigger_deprecation(
'guzzlehttp/psr7',
'2.12',
'Passing %s to Utils::streamFor() is deprecated; cast it to a string. guzzlehttp/psr7 3.0 will only accept string, resource, StreamInterface, Stringable, Iterator, callable, or null.',
\gettype($resource)
);
if (is_float($resource) && !is_finite($resource)) {
// Normalized only to avoid PHP 8.5's (string) NAN warning
// while deprecated; 3.0 rejects non-finite floats with every
// other non-string scalar.
$resource = is_nan($resource) ? 'NAN' : ($resource > 0 ? 'INF' : '-INF');
}
}
$stream = self::tryFopen('php://temp', 'r+');
if ($resource !== '') {
fwrite($stream, (string) $resource);

View File

@@ -1,688 +0,0 @@
<?php
namespace Illuminate\Pagination;
use ArrayAccess;
use Closure;
use Exception;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\ForwardsCalls;
use Illuminate\Support\Traits\Tappable;
use Illuminate\Support\Traits\TransformsToResourceCollection;
use Stringable;
use Traversable;
/**
* @template TKey of array-key
*
* @template-covariant TValue
*
* @mixin \Illuminate\Support\Collection<TKey, TValue>
*/
abstract class AbstractCursorPaginator implements Htmlable, Stringable
{
use ForwardsCalls, Tappable, TransformsToResourceCollection;
/**
* All of the items being paginated.
*
* @var \Illuminate\Support\Collection<TKey, TValue>
*/
protected $items;
/**
* The number of items to be shown per page.
*
* @var int
*/
protected $perPage;
/**
* The base path to assign to all URLs.
*
* @var string
*/
protected $path = '/';
/**
* The query parameters to add to all URLs.
*
* @var array
*/
protected $query = [];
/**
* The URL fragment to add to all URLs.
*
* @var string|null
*/
protected $fragment;
/**
* The cursor string variable used to store the page.
*
* @var string
*/
protected $cursorName = 'cursor';
/**
* The current cursor.
*
* @var \Illuminate\Pagination\Cursor|null
*/
protected $cursor;
/**
* The paginator parameters for the cursor.
*
* @var array
*/
protected $parameters;
/**
* The paginator options.
*
* @var array
*/
protected $options;
/**
* The current cursor resolver callback.
*
* @var \Closure
*/
protected static $currentCursorResolver;
/**
* Get the URL for a given cursor.
*
* @param \Illuminate\Pagination\Cursor|null $cursor
* @return string
*/
public function url($cursor)
{
// If we have any extra query string key / value pairs that need to be added
// onto the URL, we will put them in query string form and then attach it
// to the URL. This allows for extra information like sortings storage.
$parameters = is_null($cursor) ? [] : [$this->cursorName => $cursor->encode()];
if (count($this->query) > 0) {
$parameters = array_merge($this->query, $parameters);
}
return $this->path()
.(str_contains($this->path(), '?') ? '&' : '?')
.Arr::query($parameters)
.$this->buildFragment();
}
/**
* Get the URL for the previous page.
*
* @return string|null
*/
public function previousPageUrl()
{
if (is_null($previousCursor = $this->previousCursor())) {
return null;
}
return $this->url($previousCursor);
}
/**
* The URL for the next page, or null.
*
* @return string|null
*/
public function nextPageUrl()
{
if (is_null($nextCursor = $this->nextCursor())) {
return null;
}
return $this->url($nextCursor);
}
/**
* Get the "cursor" that points to the previous set of items.
*
* @return \Illuminate\Pagination\Cursor|null
*/
public function previousCursor()
{
if (is_null($this->cursor) ||
($this->cursor->pointsToPreviousItems() && ! $this->hasMore)) {
return null;
}
if ($this->items->isEmpty()) {
return null;
}
return $this->getCursorForItem($this->items->first(), false);
}
/**
* Get the "cursor" that points to the next set of items.
*
* @return \Illuminate\Pagination\Cursor|null
*/
public function nextCursor()
{
if ((is_null($this->cursor) && ! $this->hasMore) ||
(! is_null($this->cursor) && $this->cursor->pointsToNextItems() && ! $this->hasMore)) {
return null;
}
if ($this->items->isEmpty()) {
return null;
}
return $this->getCursorForItem($this->items->last(), true);
}
/**
* Get a cursor instance for the given item.
*
* @param \ArrayAccess|\stdClass $item
* @param bool $isNext
* @return \Illuminate\Pagination\Cursor
*/
public function getCursorForItem($item, $isNext = true)
{
return new Cursor($this->getParametersForItem($item), $isNext);
}
/**
* Get the cursor parameters for a given object.
*
* @param \ArrayAccess|\stdClass $item
* @return array
*
* @throws \Exception
*/
public function getParametersForItem($item)
{
return (new Collection($this->parameters))
->filter()
->flip()
->map(function ($_, $parameterName) use ($item) {
if ($item instanceof JsonResource) {
$item = $item->resource;
}
if ($item instanceof Model &&
! is_null($parameter = $this->getPivotParameterForItem($item, $parameterName))) {
return $parameter;
} elseif ($item instanceof ArrayAccess || is_array($item)) {
return $this->ensureParameterIsPrimitive(
$item[$parameterName] ?? $item[Str::afterLast($parameterName, '.')]
);
} elseif (is_object($item)) {
return $this->ensureParameterIsPrimitive(
$item->{$parameterName} ?? $item->{Str::afterLast($parameterName, '.')}
);
}
throw new Exception('Only arrays and objects are supported when cursor paginating items.');
})->toArray();
}
/**
* Get the cursor parameter value from a pivot model if applicable.
*
* @param \ArrayAccess|\stdClass $item
* @param string $parameterName
* @return string|null
*/
protected function getPivotParameterForItem($item, $parameterName)
{
$table = Str::beforeLast($parameterName, '.');
foreach ($item->getRelations() as $relation) {
if ($relation instanceof Pivot && $relation->getTable() === $table) {
return $this->ensureParameterIsPrimitive(
$relation->getAttribute(Str::afterLast($parameterName, '.'))
);
}
}
}
/**
* Ensure the parameter is a primitive type.
*
* This can resolve issues that arise the developer uses a value object for an attribute.
*
* @param mixed $parameter
* @return mixed
*/
protected function ensureParameterIsPrimitive($parameter)
{
return is_object($parameter) && method_exists($parameter, '__toString')
? (string) $parameter
: $parameter;
}
/**
* Get / set the URL fragment to be appended to URLs.
*
* @param string|null $fragment
* @return $this|string|null
*/
public function fragment($fragment = null)
{
if (is_null($fragment)) {
return $this->fragment;
}
$this->fragment = $fragment;
return $this;
}
/**
* Add a set of query string values to the paginator.
*
* @param array|string|null $key
* @param string|null $value
* @return $this
*/
public function appends($key, $value = null)
{
if (is_null($key)) {
return $this;
}
if (is_array($key)) {
return $this->appendArray($key);
}
return $this->addQuery($key, $value);
}
/**
* Add an array of query string values.
*
* @param array $keys
* @return $this
*/
protected function appendArray(array $keys)
{
foreach ($keys as $key => $value) {
$this->addQuery($key, $value);
}
return $this;
}
/**
* Add all current query string values to the paginator.
*
* @return $this
*/
public function withQueryString()
{
if (! is_null($query = Paginator::resolveQueryString())) {
return $this->appends($query);
}
return $this;
}
/**
* Add a query string value to the paginator.
*
* @param string $key
* @param string $value
* @return $this
*/
protected function addQuery($key, $value)
{
if ($key !== $this->cursorName) {
$this->query[$key] = $value;
}
return $this;
}
/**
* Build the full fragment portion of a URL.
*
* @return string
*/
protected function buildFragment()
{
return $this->fragment ? '#'.$this->fragment : '';
}
/**
* Load a set of relationships onto the mixed relationship collection.
*
* @param string $relation
* @param array $relations
* @return $this
*/
public function loadMorph($relation, $relations)
{
$this->getCollection()->loadMorph($relation, $relations);
return $this;
}
/**
* Load a set of relationship counts onto the mixed relationship collection.
*
* @param string $relation
* @param array $relations
* @return $this
*/
public function loadMorphCount($relation, $relations)
{
$this->getCollection()->loadMorphCount($relation, $relations);
return $this;
}
/**
* Get the slice of items being paginated.
*
* @return array<TKey, TValue>
*/
public function items()
{
return $this->items->all();
}
/**
* Transform each item in the slice of items using a callback.
*
* @template TThroughValue
*
* @param callable(TValue, TKey): TThroughValue $callback
* @return $this
*
* @phpstan-this-out static<TKey, TThroughValue>
*/
public function through(callable $callback)
{
$this->items->transform($callback);
return $this;
}
/**
* Get the number of items shown per page.
*
* @return int
*/
public function perPage()
{
return $this->perPage;
}
/**
* Get the current cursor being paginated.
*
* @return \Illuminate\Pagination\Cursor|null
*/
public function cursor()
{
return $this->cursor;
}
/**
* Get the query string variable used to store the cursor.
*
* @return string
*/
public function getCursorName()
{
return $this->cursorName;
}
/**
* Set the query string variable used to store the cursor.
*
* @param string $name
* @return $this
*/
public function setCursorName($name)
{
$this->cursorName = $name;
return $this;
}
/**
* Set the base path to assign to all URLs.
*
* @param string $path
* @return $this
*/
public function withPath($path)
{
return $this->setPath($path);
}
/**
* Set the base path to assign to all URLs.
*
* @param string $path
* @return $this
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Get the base path for paginator generated URLs.
*
* @return string|null
*/
public function path()
{
return $this->path;
}
/**
* Resolve the current cursor or return the default value.
*
* @param string $cursorName
* @param \Illuminate\Pagination\Cursor|null $default
* @return \Illuminate\Pagination\Cursor|null
*/
public static function resolveCurrentCursor($cursorName = 'cursor', $default = null)
{
if (isset(static::$currentCursorResolver)) {
return call_user_func(static::$currentCursorResolver, $cursorName);
}
return $default;
}
/**
* Set the current cursor resolver callback.
*
* @param \Closure $resolver
* @return void
*/
public static function currentCursorResolver(Closure $resolver)
{
static::$currentCursorResolver = $resolver;
}
/**
* Get an instance of the view factory from the resolver.
*
* @return \Illuminate\Contracts\View\Factory
*/
public static function viewFactory()
{
return Paginator::viewFactory();
}
/**
* Get an iterator for the items.
*
* @return \ArrayIterator<TKey, TValue>
*/
public function getIterator(): Traversable
{
return $this->items->getIterator();
}
/**
* Determine if the list of items is empty.
*
* @return bool
*/
public function isEmpty()
{
return $this->items->isEmpty();
}
/**
* Determine if the list of items is not empty.
*
* @return bool
*/
public function isNotEmpty()
{
return $this->items->isNotEmpty();
}
/**
* Get the number of items for the current page.
*
* @return int
*/
public function count(): int
{
return $this->items->count();
}
/**
* Get the paginator's underlying collection.
*
* @return \Illuminate\Support\Collection<TKey, TValue>
*/
public function getCollection()
{
return $this->items;
}
/**
* Set the paginator's underlying collection.
*
* @template TSetKey of array-key
* @template TSetValue
*
* @param \Illuminate\Support\Collection<TSetKey, TSetValue> $collection
* @return $this
*
* @phpstan-this-out static<TSetKey, TSetValue>
*/
public function setCollection(Collection $collection)
{
$this->items = $collection;
return $this;
}
/**
* Get the paginator options.
*
* @return array
*/
public function getOptions()
{
return $this->options;
}
/**
* Determine if the given item exists.
*
* @param TKey $key
* @return bool
*/
public function offsetExists($key): bool
{
return $this->items->has($key);
}
/**
* Get the item at the given offset.
*
* @param TKey $key
* @return TValue|null
*/
public function offsetGet($key): mixed
{
return $this->items->get($key);
}
/**
* Set the item at the given offset.
*
* @param TKey|null $key
* @param TValue $value
* @return void
*/
public function offsetSet($key, $value): void
{
$this->items->put($key, $value);
}
/**
* Unset the item at the given key.
*
* @param TKey $key
* @return void
*/
public function offsetUnset($key): void
{
$this->items->forget($key);
}
/**
* Render the contents of the paginator to HTML.
*
* @return string
*/
public function toHtml()
{
return (string) $this->render();
}
/**
* Make dynamic calls into the collection.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return $this->forwardCallTo($this->getCollection(), $method, $parameters);
}
/**
* Render the contents of the paginator when casting to a string.
*
* @return string
*/
public function __toString()
{
return (string) $this->render();
}
}

View File

@@ -1,830 +0,0 @@
<?php
namespace Illuminate\Pagination;
use Closure;
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Traits\ForwardsCalls;
use Illuminate\Support\Traits\Tappable;
use Illuminate\Support\Traits\TransformsToResourceCollection;
use Stringable;
use Traversable;
/**
* @template TKey of array-key
*
* @template-covariant TValue
*
* @mixin \Illuminate\Support\Collection<TKey, TValue>
*/
abstract class AbstractPaginator implements CanBeEscapedWhenCastToString, Htmlable, Stringable
{
use ForwardsCalls, Tappable, TransformsToResourceCollection;
/**
* All of the items being paginated.
*
* @var \Illuminate\Support\Collection<TKey, TValue>
*/
protected $items;
/**
* The number of items to be shown per page.
*
* @var int
*/
protected $perPage;
/**
* The current page being "viewed".
*
* @var int
*/
protected $currentPage;
/**
* The base path to assign to all URLs.
*
* @var string
*/
protected $path = '/';
/**
* The query parameters to add to all URLs.
*
* @var array
*/
protected $query = [];
/**
* The URL fragment to add to all URLs.
*
* @var string|null
*/
protected $fragment;
/**
* The query string variable used to store the page.
*
* @var string
*/
protected $pageName = 'page';
/**
* Indicates that the paginator's string representation should be escaped when __toString is invoked.
*
* @var bool
*/
protected $escapeWhenCastingToString = false;
/**
* The number of links to display on each side of current page link.
*
* @var int
*/
public $onEachSide = 3;
/**
* The paginator options.
*
* @var array
*/
protected $options;
/**
* The current path resolver callback.
*
* @var \Closure
*/
protected static $currentPathResolver;
/**
* The current page resolver callback.
*
* @var \Closure
*/
protected static $currentPageResolver;
/**
* The query string resolver callback.
*
* @var \Closure
*/
protected static $queryStringResolver;
/**
* The view factory resolver callback.
*
* @var \Closure
*/
protected static $viewFactoryResolver;
/**
* The default pagination view.
*
* @var string
*/
public static $defaultView = 'pagination::tailwind';
/**
* The default "simple" pagination view.
*
* @var string
*/
public static $defaultSimpleView = 'pagination::simple-tailwind';
/**
* Determine if the given value is a valid page number.
*
* @param int $page
* @return bool
*/
protected function isValidPageNumber($page)
{
return $page >= 1 && filter_var($page, FILTER_VALIDATE_INT) !== false;
}
/**
* Get the URL for the previous page.
*
* @return string|null
*/
public function previousPageUrl()
{
if ($this->currentPage() > 1) {
return $this->url($this->currentPage() - 1);
}
}
/**
* Create a range of pagination URLs.
*
* @param int $start
* @param int $end
* @return array
*/
public function getUrlRange($start, $end)
{
return Collection::range($start, $end)
->mapWithKeys(fn ($page) => [$page => $this->url($page)])
->all();
}
/**
* Get the URL for a given page number.
*
* @param int $page
* @return string
*/
public function url($page)
{
if ($page <= 0) {
$page = 1;
}
// If we have any extra query string key / value pairs that need to be added
// onto the URL, we will put them in query string form and then attach it
// to the URL. This allows for extra information like sortings storage.
$parameters = [$this->pageName => $page];
if (count($this->query) > 0) {
$parameters = array_merge($this->query, $parameters);
}
return $this->path()
.(str_contains($this->path(), '?') ? '&' : '?')
.Arr::query($parameters)
.$this->buildFragment();
}
/**
* Get / set the URL fragment to be appended to URLs.
*
* @param string|null $fragment
* @return $this|string|null
*/
public function fragment($fragment = null)
{
if (is_null($fragment)) {
return $this->fragment;
}
$this->fragment = $fragment;
return $this;
}
/**
* Add a set of query string values to the paginator.
*
* @param array|string|null $key
* @param string|null $value
* @return $this
*/
public function appends($key, $value = null)
{
if (is_null($key)) {
return $this;
}
if (is_array($key)) {
return $this->appendArray($key);
}
return $this->addQuery($key, $value);
}
/**
* Add an array of query string values.
*
* @param array $keys
* @return $this
*/
protected function appendArray(array $keys)
{
foreach ($keys as $key => $value) {
$this->addQuery($key, $value);
}
return $this;
}
/**
* Add all current query string values to the paginator.
*
* @return $this
*/
public function withQueryString()
{
if (isset(static::$queryStringResolver)) {
return $this->appends(call_user_func(static::$queryStringResolver));
}
return $this;
}
/**
* Add a query string value to the paginator.
*
* @param string $key
* @param string $value
* @return $this
*/
protected function addQuery($key, $value)
{
if ($key !== $this->pageName) {
$this->query[$key] = $value;
}
return $this;
}
/**
* Build the full fragment portion of a URL.
*
* @return string
*/
protected function buildFragment()
{
return $this->fragment ? '#'.$this->fragment : '';
}
/**
* Load a set of relationships onto the mixed relationship collection.
*
* @param string $relation
* @param array $relations
* @return $this
*/
public function loadMorph($relation, $relations)
{
$this->getCollection()->loadMorph($relation, $relations);
return $this;
}
/**
* Load a set of relationship counts onto the mixed relationship collection.
*
* @param string $relation
* @param array $relations
* @return $this
*/
public function loadMorphCount($relation, $relations)
{
$this->getCollection()->loadMorphCount($relation, $relations);
return $this;
}
/**
* Get the slice of items being paginated.
*
* @return array<TKey, TValue>
*/
public function items()
{
return $this->items->all();
}
/**
* Get the number of the first item in the slice.
*
* @return int|null
*/
public function firstItem()
{
return count($this->items) > 0 ? ($this->currentPage - 1) * $this->perPage + 1 : null;
}
/**
* Get the number of the last item in the slice.
*
* @return int|null
*/
public function lastItem()
{
return count($this->items) > 0 ? $this->firstItem() + $this->count() - 1 : null;
}
/**
* Transform each item in the slice of items using a callback.
*
* @template TMapValue
*
* @param callable(TValue, TKey): TMapValue $callback
* @return $this
*
* @phpstan-this-out static<TKey, TMapValue>
*/
public function through(callable $callback)
{
$this->items->transform($callback);
return $this;
}
/**
* Get the number of items shown per page.
*
* @return int
*/
public function perPage()
{
return $this->perPage;
}
/**
* Determine if there are enough items to split into multiple pages.
*
* @return bool
*/
public function hasPages()
{
return $this->currentPage() != 1 || $this->hasMorePages();
}
/**
* Determine if the paginator is on the first page.
*
* @return bool
*/
public function onFirstPage()
{
return $this->currentPage() <= 1;
}
/**
* Determine if the paginator is on the last page.
*
* @return bool
*/
public function onLastPage()
{
return ! $this->hasMorePages();
}
/**
* Get the current page.
*
* @return int
*/
public function currentPage()
{
return $this->currentPage;
}
/**
* Get the query string variable used to store the page.
*
* @return string
*/
public function getPageName()
{
return $this->pageName;
}
/**
* Set the query string variable used to store the page.
*
* @param string $name
* @return $this
*/
public function setPageName($name)
{
$this->pageName = $name;
return $this;
}
/**
* Set the base path to assign to all URLs.
*
* @param string $path
* @return $this
*/
public function withPath($path)
{
return $this->setPath($path);
}
/**
* Set the base path to assign to all URLs.
*
* @param string $path
* @return $this
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Set the number of links to display on each side of current page link.
*
* @param int $count
* @return $this
*/
public function onEachSide($count)
{
$this->onEachSide = $count;
return $this;
}
/**
* Get the base path for paginator generated URLs.
*
* @return string|null
*/
public function path()
{
return $this->path;
}
/**
* Resolve the current request path or return the default value.
*
* @param string $default
* @return string
*/
public static function resolveCurrentPath($default = '/')
{
if (isset(static::$currentPathResolver)) {
return call_user_func(static::$currentPathResolver);
}
return $default;
}
/**
* Set the current request path resolver callback.
*
* @param \Closure $resolver
* @return void
*/
public static function currentPathResolver(Closure $resolver)
{
static::$currentPathResolver = $resolver;
}
/**
* Resolve the current page or return the default value.
*
* @param string $pageName
* @param int $default
* @return int
*/
public static function resolveCurrentPage($pageName = 'page', $default = 1)
{
if (isset(static::$currentPageResolver)) {
return (int) call_user_func(static::$currentPageResolver, $pageName);
}
return $default;
}
/**
* Set the current page resolver callback.
*
* @param \Closure $resolver
* @return void
*/
public static function currentPageResolver(Closure $resolver)
{
static::$currentPageResolver = $resolver;
}
/**
* Resolve the query string or return the default value.
*
* @param string|array|null $default
* @return string
*/
public static function resolveQueryString($default = null)
{
if (isset(static::$queryStringResolver)) {
return (static::$queryStringResolver)();
}
return $default;
}
/**
* Set with query string resolver callback.
*
* @param \Closure $resolver
* @return void
*/
public static function queryStringResolver(Closure $resolver)
{
static::$queryStringResolver = $resolver;
}
/**
* Get an instance of the view factory from the resolver.
*
* @return \Illuminate\Contracts\View\Factory
*/
public static function viewFactory()
{
return call_user_func(static::$viewFactoryResolver);
}
/**
* Set the view factory resolver callback.
*
* @param \Closure $resolver
* @return void
*/
public static function viewFactoryResolver(Closure $resolver)
{
static::$viewFactoryResolver = $resolver;
}
/**
* Set the default pagination view.
*
* @param string $view
* @return void
*/
public static function defaultView($view)
{
static::$defaultView = $view;
}
/**
* Set the default "simple" pagination view.
*
* @param string $view
* @return void
*/
public static function defaultSimpleView($view)
{
static::$defaultSimpleView = $view;
}
/**
* Indicate that Tailwind styling should be used for generated links.
*
* @return void
*/
public static function useTailwind()
{
static::defaultView('pagination::tailwind');
static::defaultSimpleView('pagination::simple-tailwind');
}
/**
* Indicate that Bootstrap 4 styling should be used for generated links.
*
* @return void
*/
public static function useBootstrap()
{
static::useBootstrapFour();
}
/**
* Indicate that Bootstrap 3 styling should be used for generated links.
*
* @return void
*/
public static function useBootstrapThree()
{
static::defaultView('pagination::default');
static::defaultSimpleView('pagination::simple-default');
}
/**
* Indicate that Bootstrap 4 styling should be used for generated links.
*
* @return void
*/
public static function useBootstrapFour()
{
static::defaultView('pagination::bootstrap-4');
static::defaultSimpleView('pagination::simple-bootstrap-4');
}
/**
* Indicate that Bootstrap 5 styling should be used for generated links.
*
* @return void
*/
public static function useBootstrapFive()
{
static::defaultView('pagination::bootstrap-5');
static::defaultSimpleView('pagination::simple-bootstrap-5');
}
/**
* Get an iterator for the items.
*
* @return \ArrayIterator<TKey, TValue>
*/
public function getIterator(): Traversable
{
return $this->items->getIterator();
}
/**
* Determine if the list of items is empty.
*
* @return bool
*/
public function isEmpty()
{
return $this->items->isEmpty();
}
/**
* Determine if the list of items is not empty.
*
* @return bool
*/
public function isNotEmpty()
{
return $this->items->isNotEmpty();
}
/**
* Get the number of items for the current page.
*
* @return int
*/
public function count(): int
{
return $this->items->count();
}
/**
* Get the paginator's underlying collection.
*
* @return \Illuminate\Support\Collection<TKey, TValue>
*/
public function getCollection()
{
return $this->items;
}
/**
* Set the paginator's underlying collection.
*
* @param \Illuminate\Support\Collection<TKey, TValue> $collection
* @return $this
*/
public function setCollection(Collection $collection)
{
$this->items = $collection;
return $this;
}
/**
* Get the paginator options.
*
* @return array
*/
public function getOptions()
{
return $this->options;
}
/**
* Determine if the given item exists.
*
* @param TKey $key
* @return bool
*/
public function offsetExists($key): bool
{
return $this->items->has($key);
}
/**
* Get the item at the given offset.
*
* @param TKey $key
* @return TValue|null
*/
public function offsetGet($key): mixed
{
return $this->items->get($key);
}
/**
* Set the item at the given offset.
*
* @param TKey|null $key
* @param TValue $value
* @return void
*/
public function offsetSet($key, $value): void
{
$this->items->put($key, $value);
}
/**
* Unset the item at the given key.
*
* @param TKey $key
* @return void
*/
public function offsetUnset($key): void
{
$this->items->forget($key);
}
/**
* Render the contents of the paginator to HTML.
*
* @return string
*/
public function toHtml()
{
return (string) $this->render();
}
/**
* Make dynamic calls into the collection.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return $this->forwardCallTo($this->getCollection(), $method, $parameters);
}
/**
* Render the contents of the paginator when casting to a string.
*
* @return string
*/
public function __toString()
{
return $this->escapeWhenCastingToString
? e((string) $this->render())
: (string) $this->render();
}
/**
* Indicate that the paginator's string representation should be escaped when __toString is invoked.
*
* @param bool $escape
* @return $this
*/
public function escapeWhenCastingToString($escape = true)
{
$this->escapeWhenCastingToString = $escape;
return $this;
}
}

View File

@@ -1,134 +0,0 @@
<?php
namespace Illuminate\Pagination;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Collection;
use UnexpectedValueException;
/** @implements Arrayable<array-key, mixed> */
class Cursor implements Arrayable
{
/**
* The parameters associated with the cursor.
*
* @var array
*/
protected $parameters;
/**
* Determine whether the cursor points to the next or previous set of items.
*
* @var bool
*/
protected $pointsToNextItems;
/**
* Create a new cursor instance.
*
* @param array $parameters
* @param bool $pointsToNextItems
*/
public function __construct(array $parameters, $pointsToNextItems = true)
{
$this->parameters = $parameters;
$this->pointsToNextItems = $pointsToNextItems;
}
/**
* Get the given parameter from the cursor.
*
* @param string $parameterName
* @return string|null
*
* @throws \UnexpectedValueException
*/
public function parameter(string $parameterName)
{
if (! array_key_exists($parameterName, $this->parameters)) {
throw new UnexpectedValueException("Unable to find parameter [{$parameterName}] in pagination item.");
}
return $this->parameters[$parameterName];
}
/**
* Get the given parameters from the cursor.
*
* @param array $parameterNames
* @return array
*/
public function parameters(array $parameterNames)
{
return (new Collection($parameterNames))
->map(fn ($parameterName) => $this->parameter($parameterName))
->toArray();
}
/**
* Determine whether the cursor points to the next set of items.
*
* @return bool
*/
public function pointsToNextItems()
{
return $this->pointsToNextItems;
}
/**
* Determine whether the cursor points to the previous set of items.
*
* @return bool
*/
public function pointsToPreviousItems()
{
return ! $this->pointsToNextItems;
}
/**
* Get the array representation of the cursor.
*
* @return array
*/
public function toArray()
{
return array_merge($this->parameters, [
'_pointsToNextItems' => $this->pointsToNextItems,
]);
}
/**
* Get the encoded string representation of the cursor to construct a URL.
*
* @return string
*/
public function encode()
{
return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode(json_encode($this->toArray())));
}
/**
* Get a cursor instance from the encoded string representation.
*
* @param string|null $encodedString
* @return static|null
*/
public static function fromEncoded($encodedString)
{
if (! is_string($encodedString)) {
return null;
}
$parameters = json_decode(base64_decode(str_replace(['-', '_'], ['+', '/'], $encodedString)), true);
if (json_last_error() !== JSON_ERROR_NONE) {
return null;
}
$pointsToNextItems = $parameters['_pointsToNextItems'];
unset($parameters['_pointsToNextItems']);
return new static($parameters, $pointsToNextItems);
}
}

View File

@@ -1,195 +0,0 @@
<?php
namespace Illuminate\Pagination;
use ArrayAccess;
use Countable;
use Illuminate\Contracts\Pagination\CursorPaginator as PaginatorContract;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Collection;
use IteratorAggregate;
use JsonSerializable;
/**
* @template TKey of array-key
*
* @template-covariant TValue
*
* @extends AbstractCursorPaginator<TKey, TValue>
*
* @implements Arrayable<TKey, TValue>
* @implements ArrayAccess<TKey, TValue>
* @implements IteratorAggregate<TKey, TValue>
* @implements PaginatorContract<TKey, TValue>
*/
class CursorPaginator extends AbstractCursorPaginator implements Arrayable, ArrayAccess, Countable, IteratorAggregate, Jsonable, JsonSerializable, PaginatorContract
{
/**
* Indicates whether there are more items in the data source.
*
* @return bool
*/
protected $hasMore;
/**
* Create a new paginator instance.
*
* @param Collection<TKey, TValue>|Arrayable<TKey, TValue>|iterable<TKey, TValue>|null $items
* @param int $perPage
* @param \Illuminate\Pagination\Cursor|null $cursor
* @param array $options (path, query, fragment, pageName)
*/
public function __construct($items, $perPage, $cursor = null, array $options = [])
{
$this->options = $options;
foreach ($options as $key => $value) {
$this->{$key} = $value;
}
$this->perPage = (int) $perPage;
$this->cursor = $cursor;
$this->path = $this->path !== '/' ? rtrim($this->path, '/') : $this->path;
$this->setItems($items);
}
/**
* Set the items for the paginator.
*
* @param Collection<TKey, TValue>|Arrayable<TKey, TValue>|iterable<TKey, TValue>|null $items
* @return void
*/
protected function setItems($items)
{
$this->items = $items instanceof Collection ? $items : new Collection($items);
$this->hasMore = $this->items->count() > $this->perPage;
$this->items = $this->items->slice(0, $this->perPage);
if (! is_null($this->cursor) && $this->cursor->pointsToPreviousItems()) {
$this->items = $this->items->reverse()->values();
}
}
/**
* Render the paginator using the given view.
*
* @param string|null $view
* @param array $data
* @return \Illuminate\Contracts\Support\Htmlable
*/
public function links($view = null, $data = [])
{
return $this->render($view, $data);
}
/**
* Render the paginator using the given view.
*
* @param string|null $view
* @param array $data
* @return \Illuminate\Contracts\Support\Htmlable
*/
public function render($view = null, $data = [])
{
return static::viewFactory()->make($view ?: Paginator::$defaultSimpleView, array_merge($data, [
'paginator' => $this,
]));
}
/**
* Determine if there are more items in the data source.
*
* @return bool
*/
public function hasMorePages()
{
return (is_null($this->cursor) && $this->hasMore) ||
(! is_null($this->cursor) && $this->cursor->pointsToNextItems() && $this->hasMore) ||
(! is_null($this->cursor) && $this->cursor->pointsToPreviousItems());
}
/**
* Determine if there are enough items to split into multiple pages.
*
* @return bool
*/
public function hasPages()
{
return ! $this->onFirstPage() || $this->hasMorePages();
}
/**
* Determine if the paginator is on the first page.
*
* @return bool
*/
public function onFirstPage()
{
return is_null($this->cursor) || ($this->cursor->pointsToPreviousItems() && ! $this->hasMore);
}
/**
* Determine if the paginator is on the last page.
*
* @return bool
*/
public function onLastPage()
{
return ! $this->hasMorePages();
}
/**
* Get the instance as an array.
*
* @return array
*/
public function toArray()
{
return [
'data' => $this->items->toArray(),
'path' => $this->path(),
'per_page' => $this->perPage(),
'next_cursor' => $this->nextCursor()?->encode(),
'next_page_url' => $this->nextPageUrl(),
'prev_cursor' => $this->previousCursor()?->encode(),
'prev_page_url' => $this->previousPageUrl(),
];
}
/**
* Convert the object into something JSON serializable.
*
* @return array
*/
public function jsonSerialize(): array
{
return $this->toArray();
}
/**
* Convert the object to its JSON representation.
*
* @param int $options
* @return string
*/
public function toJson($options = 0)
{
return json_encode($this->jsonSerialize(), $options);
}
/**
* Convert the object to pretty print formatted JSON.
*
* @params int $options
*
* @return string
*/
public function toPrettyJson(int $options = 0)
{
return $this->toJson(JSON_PRETTY_PRINT | $options);
}
}

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) Taylor Otwell
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.

View File

@@ -1,257 +0,0 @@
<?php
namespace Illuminate\Pagination;
use ArrayAccess;
use Countable;
use Illuminate\Contracts\Pagination\LengthAwarePaginator as LengthAwarePaginatorContract;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Collection;
use IteratorAggregate;
use JsonSerializable;
/**
* @template TKey of array-key
*
* @template-covariant TValue
*
* @extends AbstractPaginator<TKey, TValue>
*
* @implements Arrayable<TKey, TValue>
* @implements ArrayAccess<TKey, TValue>
* @implements IteratorAggregate<TKey, TValue>
* @implements LengthAwarePaginatorContract<TKey, TValue>
*/
class LengthAwarePaginator extends AbstractPaginator implements Arrayable, ArrayAccess, Countable, IteratorAggregate, Jsonable, JsonSerializable, LengthAwarePaginatorContract
{
/**
* The total number of items before slicing.
*
* @var int
*/
protected $total;
/**
* The last available page.
*
* @var int
*/
protected $lastPage;
/**
* Create a new paginator instance.
*
* @param Collection<TKey, TValue>|Arrayable<TKey, TValue>|iterable<TKey, TValue>|null $items
* @param int $total
* @param int $perPage
* @param int|null $currentPage
* @param array $options (path, query, fragment, pageName)
*/
public function __construct($items, $total, $perPage, $currentPage = null, array $options = [])
{
$this->options = $options;
foreach ($options as $key => $value) {
$this->{$key} = $value;
}
$this->total = $total;
$this->perPage = (int) $perPage;
$this->lastPage = max((int) ceil($total / $perPage), 1);
$this->path = $this->path !== '/' ? rtrim($this->path, '/') : $this->path;
$this->currentPage = $this->setCurrentPage($currentPage, $this->pageName);
$this->items = $items instanceof Collection ? $items : new Collection($items);
}
/**
* Get the current page for the request.
*
* @param int $currentPage
* @param string $pageName
* @return int
*/
protected function setCurrentPage($currentPage, $pageName)
{
$currentPage = $currentPage ?: static::resolveCurrentPage($pageName);
return $this->isValidPageNumber($currentPage) ? (int) $currentPage : 1;
}
/**
* Render the paginator using the given view.
*
* @param string|null $view
* @param array $data
* @return \Illuminate\Contracts\Support\Htmlable
*/
public function links($view = null, $data = [])
{
return $this->render($view, $data);
}
/**
* Render the paginator using the given view.
*
* @param string|null $view
* @param array $data
* @return \Illuminate\Contracts\Support\Htmlable
*/
public function render($view = null, $data = [])
{
return static::viewFactory()->make($view ?: static::$defaultView, array_merge($data, [
'paginator' => $this,
'elements' => $this->elements(),
]));
}
/**
* Get the paginator links as a collection (for JSON responses).
*
* @return \Illuminate\Support\Collection
*/
public function linkCollection()
{
return (new Collection($this->elements()))->flatMap(function ($item) {
if (! is_array($item)) {
return [['url' => null, 'label' => '...', 'active' => false]];
}
return (new Collection($item))->map(function ($url, $page) {
return [
'url' => $url,
'label' => (string) $page,
'page' => $page,
'active' => $this->currentPage() === $page,
];
});
})->prepend([
'url' => $this->previousPageUrl(),
'label' => function_exists('__') ? __('pagination.previous') : 'Previous',
'page' => $this->currentPage() > 1 ? $this->currentPage() - 1 : null,
'active' => false,
])->push([
'url' => $this->nextPageUrl(),
'label' => function_exists('__') ? __('pagination.next') : 'Next',
'page' => $this->hasMorePages() ? $this->currentPage() + 1 : null,
'active' => false,
]);
}
/**
* Get the array of elements to pass to the view.
*
* @return array
*/
protected function elements()
{
$window = UrlWindow::make($this);
return array_filter([
$window['first'],
is_array($window['slider']) ? '...' : null,
$window['slider'],
is_array($window['last']) ? '...' : null,
$window['last'],
]);
}
/**
* Get the total number of items being paginated.
*
* @return int
*/
public function total()
{
return $this->total;
}
/**
* Determine if there are more items in the data source.
*
* @return bool
*/
public function hasMorePages()
{
return $this->currentPage() < $this->lastPage();
}
/**
* Get the URL for the next page.
*
* @return string|null
*/
public function nextPageUrl()
{
if ($this->hasMorePages()) {
return $this->url($this->currentPage() + 1);
}
}
/**
* Get the last page.
*
* @return int
*/
public function lastPage()
{
return $this->lastPage;
}
/**
* Get the instance as an array.
*
* @return array
*/
public function toArray()
{
return [
'current_page' => $this->currentPage(),
'data' => $this->items->toArray(),
'first_page_url' => $this->url(1),
'from' => $this->firstItem(),
'last_page' => $this->lastPage(),
'last_page_url' => $this->url($this->lastPage()),
'links' => $this->linkCollection()->toArray(),
'next_page_url' => $this->nextPageUrl(),
'path' => $this->path(),
'per_page' => $this->perPage(),
'prev_page_url' => $this->previousPageUrl(),
'to' => $this->lastItem(),
'total' => $this->total(),
];
}
/**
* Convert the object into something JSON serializable.
*
* @return array
*/
public function jsonSerialize(): array
{
return $this->toArray();
}
/**
* Convert the object to its JSON representation.
*
* @param int $options
* @return string
*/
public function toJson($options = 0)
{
return json_encode($this->jsonSerialize(), $options);
}
/**
* Convert the object to pretty print formatted JSON.
*
* @params int $options
*
* @return string
*/
public function toPrettyJson(int $options = 0)
{
return $this->toJson(JSON_PRETTY_PRINT | $options);
}
}

View File

@@ -1,34 +0,0 @@
<?php
namespace Illuminate\Pagination;
use Illuminate\Support\ServiceProvider;
class PaginationServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->loadViewsFrom(__DIR__.'/resources/views', 'pagination');
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__.'/resources/views' => $this->app->resourcePath('views/vendor/pagination'),
], 'laravel-pagination');
}
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
PaginationState::resolveUsing($this->app);
}
}

View File

@@ -1,35 +0,0 @@
<?php
namespace Illuminate\Pagination;
class PaginationState
{
/**
* Bind the pagination state resolvers using the given application container as a base.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return void
*/
public static function resolveUsing($app)
{
Paginator::viewFactoryResolver(fn () => $app['view']);
Paginator::currentPathResolver(fn () => $app['request']->url());
Paginator::currentPageResolver(function ($pageName = 'page') use ($app) {
$page = $app['request']->input($pageName);
if (filter_var($page, FILTER_VALIDATE_INT) !== false && (int) $page >= 1) {
return (int) $page;
}
return 1;
});
Paginator::queryStringResolver(fn () => $app['request']->query());
CursorPaginator::currentCursorResolver(function ($cursorName = 'cursor') use ($app) {
return Cursor::fromEncoded($app['request']->input($cursorName));
});
}
}

View File

@@ -1,200 +0,0 @@
<?php
namespace Illuminate\Pagination;
use ArrayAccess;
use Countable;
use Illuminate\Contracts\Pagination\Paginator as PaginatorContract;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Collection;
use IteratorAggregate;
use JsonSerializable;
/**
* @template TKey of array-key
*
* @template-covariant TValue
*
* @extends AbstractPaginator<TKey, TValue>
*
* @implements Arrayable<TKey, TValue>
* @implements ArrayAccess<TKey, TValue>
* @implements IteratorAggregate<TKey, TValue>
* @implements PaginatorContract<TKey, TValue>
*/
class Paginator extends AbstractPaginator implements Arrayable, ArrayAccess, Countable, IteratorAggregate, Jsonable, JsonSerializable, PaginatorContract
{
/**
* Determine if there are more items in the data source.
*
* @return bool
*/
protected $hasMore;
/**
* Create a new paginator instance.
*
* @param Collection<TKey, TValue>|Arrayable<TKey, TValue>|iterable<TKey, TValue> $items
* @param int $perPage
* @param int|null $currentPage
* @param array $options (path, query, fragment, pageName)
*/
public function __construct($items, $perPage, $currentPage = null, array $options = [])
{
$this->options = $options;
foreach ($options as $key => $value) {
$this->{$key} = $value;
}
$this->perPage = $perPage;
$this->currentPage = $this->setCurrentPage($currentPage);
$this->path = $this->path !== '/' ? rtrim($this->path, '/') : $this->path;
$this->setItems($items);
}
/**
* Get the current page for the request.
*
* @param int $currentPage
* @return int
*/
protected function setCurrentPage($currentPage)
{
$currentPage = $currentPage ?: static::resolveCurrentPage();
return $this->isValidPageNumber($currentPage) ? (int) $currentPage : 1;
}
/**
* Set the items for the paginator.
*
* @param Collection<TKey, TValue>|Arrayable<TKey, TValue>|iterable<TKey, TValue>|null $items
* @return void
*/
protected function setItems($items)
{
$this->items = $items instanceof Collection ? $items : new Collection($items);
$this->hasMore = $this->items->count() > $this->perPage;
$this->items = $this->items->slice(0, $this->perPage);
}
/**
* Get the URL for the next page.
*
* @return string|null
*/
public function nextPageUrl()
{
if ($this->hasMorePages()) {
return $this->url($this->currentPage() + 1);
}
}
/**
* Render the paginator using the given view.
*
* @param string|null $view
* @param array $data
* @return string
*/
public function links($view = null, $data = [])
{
return $this->render($view, $data);
}
/**
* Render the paginator using the given view.
*
* @param string|null $view
* @param array $data
* @return \Illuminate\Contracts\Support\Htmlable
*/
public function render($view = null, $data = [])
{
return static::viewFactory()->make($view ?: static::$defaultSimpleView, array_merge($data, [
'paginator' => $this,
]));
}
/**
* Manually indicate that the paginator does have more pages.
*
* @param bool $hasMore
* @return $this
*/
public function hasMorePagesWhen($hasMore = true)
{
$this->hasMore = $hasMore;
return $this;
}
/**
* Determine if there are more items in the data source.
*
* @return bool
*/
public function hasMorePages()
{
return $this->hasMore;
}
/**
* Get the instance as an array.
*
* @return array
*/
public function toArray()
{
return [
'current_page' => $this->currentPage(),
'current_page_url' => $this->url($this->currentPage()),
'data' => $this->items->toArray(),
'first_page_url' => $this->url(1),
'from' => $this->firstItem(),
'next_page_url' => $this->nextPageUrl(),
'path' => $this->path(),
'per_page' => $this->perPage(),
'prev_page_url' => $this->previousPageUrl(),
'to' => $this->lastItem(),
];
}
/**
* Convert the object into something JSON serializable.
*
* @return array
*/
public function jsonSerialize(): array
{
return $this->toArray();
}
/**
* Convert the object to its JSON representation.
*
* @param int $options
* @return string
*/
public function toJson($options = 0)
{
return json_encode($this->jsonSerialize(), $options);
}
/**
* Convert the object to pretty print formatted JSON.
*
* @params int $options
*
* @return string
*/
public function toPrettyJson(int $options = 0)
{
return $this->toJson(JSON_PRETTY_PRINT | $options);
}
}

View File

@@ -1,219 +0,0 @@
<?php
namespace Illuminate\Pagination;
use Illuminate\Contracts\Pagination\LengthAwarePaginator as PaginatorContract;
class UrlWindow
{
/**
* The paginator implementation.
*
* @var \Illuminate\Contracts\Pagination\LengthAwarePaginator
*/
protected $paginator;
/**
* Create a new URL window instance.
*
* @param \Illuminate\Contracts\Pagination\LengthAwarePaginator $paginator
*/
public function __construct(PaginatorContract $paginator)
{
$this->paginator = $paginator;
}
/**
* Create a new URL window instance.
*
* @param \Illuminate\Contracts\Pagination\LengthAwarePaginator $paginator
* @return array
*/
public static function make(PaginatorContract $paginator)
{
return (new static($paginator))->get();
}
/**
* Get the window of URLs to be shown.
*
* @return array
*/
public function get()
{
$onEachSide = $this->paginator->onEachSide;
if ($this->paginator->lastPage() < ($onEachSide * 2) + 8) {
return $this->getSmallSlider();
}
return $this->getUrlSlider($onEachSide);
}
/**
* Get the slider of URLs there are not enough pages to slide.
*
* @return array
*/
protected function getSmallSlider()
{
return [
'first' => $this->paginator->getUrlRange(1, $this->lastPage()),
'slider' => null,
'last' => null,
];
}
/**
* Create a URL slider links.
*
* @param int $onEachSide
* @return array
*/
protected function getUrlSlider($onEachSide)
{
$window = $onEachSide + 4;
if (! $this->hasPages()) {
return ['first' => null, 'slider' => null, 'last' => null];
}
// If the current page is very close to the beginning of the page range, we will
// just render the beginning of the page range, followed by the last 2 of the
// links in this list, since we will not have room to create a full slider.
if ($this->currentPage() <= $window) {
return $this->getSliderTooCloseToBeginning($window, $onEachSide);
}
// If the current page is close to the ending of the page range we will just get
// this first couple pages, followed by a larger window of these ending pages
// since we're too close to the end of the list to create a full on slider.
elseif ($this->currentPage() > ($this->lastPage() - $window)) {
return $this->getSliderTooCloseToEnding($window, $onEachSide);
}
// If we have enough room on both sides of the current page to build a slider we
// will surround it with both the beginning and ending caps, with this window
// of pages in the middle providing a Google style sliding paginator setup.
return $this->getFullSlider($onEachSide);
}
/**
* Get the slider of URLs when too close to the beginning of the window.
*
* @param int $window
* @param int $onEachSide
* @return array
*/
protected function getSliderTooCloseToBeginning($window, $onEachSide)
{
return [
'first' => $this->paginator->getUrlRange(1, $window + $onEachSide),
'slider' => null,
'last' => $this->getFinish(),
];
}
/**
* Get the slider of URLs when too close to the ending of the window.
*
* @param int $window
* @param int $onEachSide
* @return array
*/
protected function getSliderTooCloseToEnding($window, $onEachSide)
{
$last = $this->paginator->getUrlRange(
$this->lastPage() - ($window + ($onEachSide - 1)),
$this->lastPage()
);
return [
'first' => $this->getStart(),
'slider' => null,
'last' => $last,
];
}
/**
* Get the slider of URLs when a full slider can be made.
*
* @param int $onEachSide
* @return array
*/
protected function getFullSlider($onEachSide)
{
return [
'first' => $this->getStart(),
'slider' => $this->getAdjacentUrlRange($onEachSide),
'last' => $this->getFinish(),
];
}
/**
* Get the page range for the current page window.
*
* @param int $onEachSide
* @return array
*/
public function getAdjacentUrlRange($onEachSide)
{
return $this->paginator->getUrlRange(
$this->currentPage() - $onEachSide,
$this->currentPage() + $onEachSide
);
}
/**
* Get the starting URLs of a pagination slider.
*
* @return array
*/
public function getStart()
{
return $this->paginator->getUrlRange(1, 2);
}
/**
* Get the ending URLs of a pagination slider.
*
* @return array
*/
public function getFinish()
{
return $this->paginator->getUrlRange(
$this->lastPage() - 1,
$this->lastPage()
);
}
/**
* Determine if the underlying paginator being presented has pages to show.
*
* @return bool
*/
public function hasPages()
{
return $this->paginator->lastPage() > 1;
}
/**
* Get the current page from the paginator.
*
* @return int
*/
protected function currentPage()
{
return $this->paginator->currentPage();
}
/**
* Get the last page from the paginator.
*
* @return int
*/
protected function lastPage()
{
return $this->paginator->lastPage();
}
}

View File

@@ -1,37 +0,0 @@
{
"name": "illuminate/pagination",
"description": "The Illuminate Pagination package.",
"license": "MIT",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"require": {
"php": "^8.2",
"ext-filter": "*",
"illuminate/collections": "^12.0",
"illuminate/contracts": "^12.0",
"illuminate/support": "^12.0"
},
"autoload": {
"psr-4": {
"Illuminate\\Pagination\\": ""
}
},
"extra": {
"branch-alias": {
"dev-master": "12.x-dev"
}
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev"
}

View File

@@ -1,46 +0,0 @@
@if ($paginator->hasPages())
<nav>
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
<span class="page-link" aria-hidden="true">&lsaquo;</span>
</li>
@else
<li class="page-item">
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">&lsaquo;</a>
</li>
@endif
{{-- Pagination Elements --}}
@foreach ($elements as $element)
{{-- "Three Dots" Separator --}}
@if (is_string($element))
<li class="page-item disabled" aria-disabled="true"><span class="page-link">{{ $element }}</span></li>
@endif
{{-- Array Of Links --}}
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<li class="page-item active" aria-current="page"><span class="page-link">{{ $page }}</span></li>
@else
<li class="page-item"><a class="page-link" href="{{ $url }}">{{ $page }}</a></li>
@endif
@endforeach
@endif
@endforeach
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li class="page-item">
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">&rsaquo;</a>
</li>
@else
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
<span class="page-link" aria-hidden="true">&rsaquo;</span>
</li>
@endif
</ul>
</nav>
@endif

View File

@@ -1,88 +0,0 @@
@if ($paginator->hasPages())
<nav class="d-flex justify-items-center justify-content-between">
<div class="d-flex justify-content-between flex-fill d-sm-none">
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="page-item disabled" aria-disabled="true">
<span class="page-link">@lang('pagination.previous')</span>
</li>
@else
<li class="page-item">
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">@lang('pagination.previous')</a>
</li>
@endif
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li class="page-item">
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a>
</li>
@else
<li class="page-item disabled" aria-disabled="true">
<span class="page-link">@lang('pagination.next')</span>
</li>
@endif
</ul>
</div>
<div class="d-none flex-sm-fill d-sm-flex align-items-sm-center justify-content-sm-between">
<div>
<p class="small text-muted">
{!! __('Showing') !!}
<span class="fw-semibold">{{ $paginator->firstItem() }}</span>
{!! __('to') !!}
<span class="fw-semibold">{{ $paginator->lastItem() }}</span>
{!! __('of') !!}
<span class="fw-semibold">{{ $paginator->total() }}</span>
{!! __('results') !!}
</p>
</div>
<div>
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
<span class="page-link" aria-hidden="true">&lsaquo;</span>
</li>
@else
<li class="page-item">
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">&lsaquo;</a>
</li>
@endif
{{-- Pagination Elements --}}
@foreach ($elements as $element)
{{-- "Three Dots" Separator --}}
@if (is_string($element))
<li class="page-item disabled" aria-disabled="true"><span class="page-link">{{ $element }}</span></li>
@endif
{{-- Array Of Links --}}
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<li class="page-item active" aria-current="page"><span class="page-link">{{ $page }}</span></li>
@else
<li class="page-item"><a class="page-link" href="{{ $url }}">{{ $page }}</a></li>
@endif
@endforeach
@endif
@endforeach
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li class="page-item">
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">&rsaquo;</a>
</li>
@else
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
<span class="page-link" aria-hidden="true">&rsaquo;</span>
</li>
@endif
</ul>
</div>
</div>
</nav>
@endif

View File

@@ -1,46 +0,0 @@
@if ($paginator->hasPages())
<nav>
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
<span aria-hidden="true">&lsaquo;</span>
</li>
@else
<li>
<a href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">&lsaquo;</a>
</li>
@endif
{{-- Pagination Elements --}}
@foreach ($elements as $element)
{{-- "Three Dots" Separator --}}
@if (is_string($element))
<li class="disabled" aria-disabled="true"><span>{{ $element }}</span></li>
@endif
{{-- Array Of Links --}}
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<li class="active" aria-current="page"><span>{{ $page }}</span></li>
@else
<li><a href="{{ $url }}">{{ $page }}</a></li>
@endif
@endforeach
@endif
@endforeach
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li>
<a href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">&rsaquo;</a>
</li>
@else
<li class="disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
<span aria-hidden="true">&rsaquo;</span>
</li>
@endif
</ul>
</nav>
@endif

View File

@@ -1,36 +0,0 @@
@if ($paginator->hasPages())
<div class="ui pagination menu" role="navigation">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<a class="icon item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')"> <i class="left chevron icon"></i> </a>
@else
<a class="icon item" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')"> <i class="left chevron icon"></i> </a>
@endif
{{-- Pagination Elements --}}
@foreach ($elements as $element)
{{-- "Three Dots" Separator --}}
@if (is_string($element))
<a class="icon item disabled" aria-disabled="true">{{ $element }}</a>
@endif
{{-- Array Of Links --}}
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<a class="item active" href="{{ $url }}" aria-current="page">{{ $page }}</a>
@else
<a class="item" href="{{ $url }}">{{ $page }}</a>
@endif
@endforeach
@endif
@endforeach
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<a class="icon item" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')"> <i class="right chevron icon"></i> </a>
@else
<a class="icon item disabled" aria-disabled="true" aria-label="@lang('pagination.next')"> <i class="right chevron icon"></i> </a>
@endif
</div>
@endif

View File

@@ -1,27 +0,0 @@
@if ($paginator->hasPages())
<nav>
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="page-item disabled" aria-disabled="true">
<span class="page-link">@lang('pagination.previous')</span>
</li>
@else
<li class="page-item">
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">@lang('pagination.previous')</a>
</li>
@endif
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li class="page-item">
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a>
</li>
@else
<li class="page-item disabled" aria-disabled="true">
<span class="page-link">@lang('pagination.next')</span>
</li>
@endif
</ul>
</nav>
@endif

View File

@@ -1,29 +0,0 @@
@if ($paginator->hasPages())
<nav role="navigation" aria-label="{!! __('Pagination Navigation') !!}">
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="page-item disabled" aria-disabled="true">
<span class="page-link">{!! __('pagination.previous') !!}</span>
</li>
@else
<li class="page-item">
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">
{!! __('pagination.previous') !!}
</a>
</li>
@endif
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li class="page-item">
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">{!! __('pagination.next') !!}</a>
</li>
@else
<li class="page-item disabled" aria-disabled="true">
<span class="page-link">{!! __('pagination.next') !!}</span>
</li>
@endif
</ul>
</nav>
@endif

View File

@@ -1,19 +0,0 @@
@if ($paginator->hasPages())
<nav>
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="disabled" aria-disabled="true"><span>@lang('pagination.previous')</span></li>
@else
<li><a href="{{ $paginator->previousPageUrl() }}" rel="prev">@lang('pagination.previous')</a></li>
@endif
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li><a href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a></li>
@else
<li class="disabled" aria-disabled="true"><span>@lang('pagination.next')</span></li>
@endif
</ul>
</nav>
@endif

View File

@@ -1,25 +0,0 @@
@if ($paginator->hasPages())
<nav role="navigation" aria-label="{{ __('Pagination Navigation') }}" class="flex gap-2 items-center justify-between">
@if ($paginator->onFirstPage())
<span class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-600 bg-white border border-gray-300 cursor-not-allowed leading-5 rounded-md dark:text-gray-300 dark:bg-gray-700 dark:border-gray-600">
{!! __('pagination.previous') !!}
</span>
@else
<a href="{{ $paginator->previousPageUrl() }}" rel="prev" class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-800 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-700 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-800 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-200 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-900 dark:hover:text-gray-200">
{!! __('pagination.previous') !!}
</a>
@endif
@if ($paginator->hasMorePages())
<a href="{{ $paginator->nextPageUrl() }}" rel="next" class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-800 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-700 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-800 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-200 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-900 dark:hover:text-gray-200">
{!! __('pagination.next') !!}
</a>
@else
<span class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-600 bg-white border border-gray-300 cursor-not-allowed leading-5 rounded-md dark:text-gray-300 dark:bg-gray-700 dark:border-gray-600">
{!! __('pagination.next') !!}
</span>
@endif
</nav>
@endif

View File

@@ -1,111 +0,0 @@
@if ($paginator->hasPages())
<nav role="navigation" aria-label="{{ __('Pagination Navigation') }}">
<div class="flex gap-2 items-center justify-between sm:hidden">
@if ($paginator->onFirstPage())
<span class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-600 bg-white border border-gray-300 cursor-not-allowed leading-5 rounded-md dark:text-gray-300 dark:bg-gray-700 dark:border-gray-600">
{!! __('pagination.previous') !!}
</span>
@else
<a href="{{ $paginator->previousPageUrl() }}" rel="prev" class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-800 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-700 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-800 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-200 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-900 dark:hover:text-gray-200">
{!! __('pagination.previous') !!}
</a>
@endif
@if ($paginator->hasMorePages())
<a href="{{ $paginator->nextPageUrl() }}" rel="next" class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-800 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-700 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-800 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-200 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-900 dark:hover:text-gray-200">
{!! __('pagination.next') !!}
</a>
@else
<span class="inline-flex items-center px-4 py-2 text-sm font-medium text-gray-600 bg-white border border-gray-300 cursor-not-allowed leading-5 rounded-md dark:text-gray-300 dark:bg-gray-700 dark:border-gray-600">
{!! __('pagination.next') !!}
</span>
@endif
</div>
<div class="hidden sm:flex-1 sm:flex sm:gap-2 sm:items-center sm:justify-between">
<div>
<p class="text-sm text-gray-700 leading-5 dark:text-gray-600">
{!! __('Showing') !!}
@if ($paginator->firstItem())
<span class="font-medium">{{ $paginator->firstItem() }}</span>
{!! __('to') !!}
<span class="font-medium">{{ $paginator->lastItem() }}</span>
@else
{{ $paginator->count() }}
@endif
{!! __('of') !!}
<span class="font-medium">{{ $paginator->total() }}</span>
{!! __('results') !!}
</p>
</div>
<div>
<span class="inline-flex rtl:flex-row-reverse shadow-sm rounded-md">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<span aria-disabled="true" aria-label="{{ __('pagination.previous') }}">
<span class="inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-not-allowed rounded-l-md leading-5 dark:bg-gray-700 dark:border-gray-600 dark:text-gray-400" aria-hidden="true">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
</span>
</span>
@else
<a href="{{ $paginator->previousPageUrl() }}" rel="prev" class="inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-l-md leading-5 hover:text-gray-400 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:active:bg-gray-700 dark:focus:border-blue-800 dark:text-gray-300 dark:hover:bg-gray-900 dark:hover:text-gray-300" aria-label="{{ __('pagination.previous') }}">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
</a>
@endif
{{-- Pagination Elements --}}
@foreach ($elements as $element)
{{-- "Three Dots" Separator --}}
@if (is_string($element))
<span aria-disabled="true">
<span class="inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 cursor-default leading-5 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300">{{ $element }}</span>
</span>
@endif
{{-- Array Of Links --}}
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<span aria-current="page">
<span class="inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-gray-200 border border-gray-300 cursor-default leading-5 dark:bg-gray-700 dark:border-gray-600 dark:text-gray-300">{{ $page }}</span>
</span>
@else
<a href="{{ $url }}" class="inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 hover:text-gray-700 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:hover:text-gray-300 dark:active:bg-gray-700 dark:focus:border-blue-800 hover:bg-gray-100 dark:hover:bg-gray-900" aria-label="{{ __('Go to page :page', ['page' => $page]) }}">
{{ $page }}
</a>
@endif
@endforeach
@endif
@endforeach
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<a href="{{ $paginator->nextPageUrl() }}" rel="next" class="inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-r-md leading-5 hover:text-gray-400 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:active:bg-gray-700 dark:focus:border-blue-800 dark:text-gray-300 dark:hover:bg-gray-900 dark:hover:text-gray-300" aria-label="{{ __('pagination.next') }}">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
</svg>
</a>
@else
<span aria-disabled="true" aria-label="{{ __('pagination.next') }}">
<span class="inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-not-allowed rounded-r-md leading-5 dark:bg-gray-700 dark:border-gray-600 dark:text-gray-400" aria-hidden="true">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
</svg>
</span>
</span>
@endif
</span>
</div>
</div>
</nav>
@endif

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) Taylor Otwell
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.

View File

@@ -1,213 +0,0 @@
<?php
namespace Illuminate\Support;
use ReflectionAttribute;
use ReflectionClass;
use ReflectionEnum;
use ReflectionMethod;
use ReflectionNamedType;
use ReflectionUnionType;
class Reflector
{
/**
* This is a PHP 7.4 compatible implementation of is_callable.
*
* @param mixed $var
* @param bool $syntaxOnly
* @return bool
*/
public static function isCallable($var, $syntaxOnly = false)
{
if (! is_array($var)) {
return is_callable($var, $syntaxOnly);
}
if (! isset($var[0], $var[1]) || ! is_string($var[1] ?? null)) {
return false;
}
if ($syntaxOnly &&
(is_string($var[0]) || is_object($var[0])) &&
is_string($var[1])) {
return true;
}
$class = is_object($var[0]) ? get_class($var[0]) : $var[0];
$method = $var[1];
if (! class_exists($class)) {
return false;
}
if (method_exists($class, $method)) {
return (new ReflectionMethod($class, $method))->isPublic();
}
if (is_object($var[0]) && method_exists($class, '__call')) {
return (new ReflectionMethod($class, '__call'))->isPublic();
}
if (! is_object($var[0]) && method_exists($class, '__callStatic')) {
return (new ReflectionMethod($class, '__callStatic'))->isPublic();
}
return false;
}
/**
* Get the specified class attribute, optionally following an inheritance chain.
*
* @template TAttribute of object
*
* @param object|class-string $objectOrClass
* @param class-string<TAttribute> $attribute
* @param bool $ascend
* @return TAttribute|null
*/
public static function getClassAttribute($objectOrClass, $attribute, $ascend = false)
{
return static::getClassAttributes($objectOrClass, $attribute, $ascend)->flatten()->first();
}
/**
* Get the specified class attribute(s), optionally following an inheritance chain.
*
* @template TTarget of object
* @template TAttribute of object
*
* @param TTarget|class-string<TTarget> $objectOrClass
* @param class-string<TAttribute> $attribute
* @param bool $includeParents
* @return ($includeParents is true ? Collection<class-string<contravariant TTarget>, Collection<int, TAttribute>> : Collection<int, TAttribute>)
*/
public static function getClassAttributes($objectOrClass, $attribute, $includeParents = false)
{
$reflectionClass = new ReflectionClass($objectOrClass);
$attributes = [];
do {
$attributes[$reflectionClass->name] = new Collection(array_map(
fn (ReflectionAttribute $reflectionAttribute) => $reflectionAttribute->newInstance(),
$reflectionClass->getAttributes($attribute)
));
} while ($includeParents && false !== $reflectionClass = $reflectionClass->getParentClass());
return $includeParents ? new Collection($attributes) : array_first($attributes);
}
/**
* Get the class name of the given parameter's type, if possible.
*
* @param \ReflectionParameter $parameter
* @return string|null
*/
public static function getParameterClassName($parameter)
{
$type = $parameter->getType();
if (! $type instanceof ReflectionNamedType || $type->isBuiltin()) {
return;
}
return static::getTypeName($parameter, $type);
}
/**
* Get the class names of the given parameter's type, including union types.
*
* @param \ReflectionParameter $parameter
* @return array
*/
public static function getParameterClassNames($parameter)
{
$type = $parameter->getType();
if (! $type instanceof ReflectionUnionType) {
return array_filter([static::getParameterClassName($parameter)]);
}
$unionTypes = [];
foreach ($type->getTypes() as $listedType) {
if (! $listedType instanceof ReflectionNamedType || $listedType->isBuiltin()) {
continue;
}
$unionTypes[] = static::getTypeName($parameter, $listedType);
}
return array_filter($unionTypes);
}
/**
* Get the given type's class name.
*
* @param \ReflectionParameter $parameter
* @param \ReflectionNamedType $type
* @return string
*/
protected static function getTypeName($parameter, $type)
{
$name = $type->getName();
if (! is_null($class = $parameter->getDeclaringClass())) {
if ($name === 'self') {
return $class->getName();
}
if ($name === 'parent' && $parent = $class->getParentClass()) {
return $parent->getName();
}
}
return $name;
}
/**
* Determine if the parameter's type is a subclass of the given type.
*
* @param \ReflectionParameter $parameter
* @param string $className
* @return bool
*/
public static function isParameterSubclassOf($parameter, $className)
{
$paramClassName = static::getParameterClassName($parameter);
return $paramClassName
&& (class_exists($paramClassName) || interface_exists($paramClassName))
&& (new ReflectionClass($paramClassName))->isSubclassOf($className);
}
/**
* Determine if the parameter's type is a Backed Enum with a string backing type.
*
* @param \ReflectionParameter $parameter
* @return bool
*/
public static function isParameterBackedEnumWithStringBackingType($parameter)
{
if (! $parameter->getType() instanceof ReflectionNamedType) {
return false;
}
$backedEnumClass = $parameter->getType()?->getName();
if (is_null($backedEnumClass)) {
return false;
}
if (enum_exists($backedEnumClass)) {
$reflectionBackedEnum = new ReflectionEnum($backedEnumClass);
return $reflectionBackedEnum->isBacked()
&& $reflectionBackedEnum->getBackingType()->getName() == 'string';
}
return false;
}
}

View File

@@ -1,126 +0,0 @@
<?php
namespace Illuminate\Support\Traits;
use Closure;
use Illuminate\Support\Collection;
use Illuminate\Support\Reflector;
use ReflectionFunction;
use ReflectionIntersectionType;
use ReflectionUnionType;
use RuntimeException;
trait ReflectsClosures
{
/**
* Get the class name of the first parameter of the given Closure.
*
* @param \Closure $closure
* @return string
*
* @throws \ReflectionException
* @throws \RuntimeException
*/
protected function firstClosureParameterType(Closure $closure)
{
$types = array_values($this->closureParameterTypes($closure));
if (! $types) {
throw new RuntimeException('The given Closure has no parameters.');
}
if ($types[0] === null) {
throw new RuntimeException('The first parameter of the given Closure is missing a type hint.');
}
return $types[0];
}
/**
* Get the class names of the first parameter of the given Closure, including union types.
*
* @param \Closure $closure
* @return array
*
* @throws \ReflectionException
* @throws \RuntimeException
*/
protected function firstClosureParameterTypes(Closure $closure)
{
$reflection = new ReflectionFunction($closure);
$types = (new Collection($reflection->getParameters()))
->mapWithKeys(function ($parameter) {
if ($parameter->isVariadic()) {
return [$parameter->getName() => null];
}
return [$parameter->getName() => Reflector::getParameterClassNames($parameter)];
})
->filter()
->values()
->all();
if (empty($types)) {
throw new RuntimeException('The given Closure has no parameters.');
}
if (isset($types[0]) && empty($types[0])) {
throw new RuntimeException('The first parameter of the given Closure is missing a type hint.');
}
return $types[0];
}
/**
* Get the class names / types of the parameters of the given Closure.
*
* @param \Closure $closure
* @return array
*
* @throws \ReflectionException
*/
protected function closureParameterTypes(Closure $closure)
{
$reflection = new ReflectionFunction($closure);
return (new Collection($reflection->getParameters()))
->mapWithKeys(function ($parameter) {
if ($parameter->isVariadic()) {
return [$parameter->getName() => null];
}
return [$parameter->getName() => Reflector::getParameterClassName($parameter)];
})
->all();
}
/**
* Get the class names / types of the return type of the given Closure.
*
* @param \Closure $closure
* @return list<class-string>
*
* @throws \ReflectionException
*/
protected function closureReturnTypes(Closure $closure)
{
$reflection = new ReflectionFunction($closure);
if ($reflection->getReturnType() === null ||
$reflection->getReturnType() instanceof ReflectionIntersectionType) {
return [];
}
$types = $reflection->getReturnType() instanceof ReflectionUnionType
? $reflection->getReturnType()->getTypes()
: [$reflection->getReturnType()];
return (new Collection($types))
->reject(fn ($type) => $type->isBuiltin())
->reject(fn ($type) => in_array($type->getName(), ['static', 'self']))
->map(fn ($type) => $type->getName())
->values()
->all();
}
}

Some files were not shown because too many files have changed in this diff Show More