MERGE_CODE MERGED

This commit is contained in:
VE10-Sanjeev 2024-08-16 10:55:42 +00:00
parent 440c772645
commit 84adb4e031
275 changed files with 2585 additions and 2112 deletions

View File

@ -27,6 +27,7 @@ $routes->post('user/Deleteuserdepartment', 'User::Deleteuserdepartment');
// $routes->match(['GET', 'POST', 'PUT', 'DELETE'],'resetPasswordConfirmUser/(:any)/(:any)', 'Login::resetPasswordConfirmUser/$1/$2'); // $routes->match(['GET', 'POST', 'PUT', 'DELETE'],'resetPasswordConfirmUser/(:any)/(:any)', 'Login::resetPasswordConfirmUser/$1/$2');
// $routes->match(['GET', 'POST', 'PUT', 'DELETE'],'createPasswordUser', 'Login::createPasswordUser'); // $routes->match(['GET', 'POST', 'PUT', 'DELETE'],'createPasswordUser', 'Login::createPasswordUser');
$routes->get('dashboard', 'User::index'); $routes->get('dashboard', 'User::index');
$routes->get('sales_invoice', 'User::sales_invoice');
$routes->get('reports', 'Report::index'); $routes->get('reports', 'Report::index');
// User Routes // User Routes
@ -352,3 +353,11 @@ $routes->get('qualityreportlistinward', 'Quality::reportListInward');
$routes->get('shortagematerialListing', 'Rawmaterialdetails::shortagematerialListing'); $routes->get('shortagematerialListing', 'Rawmaterialdetails::shortagematerialListing');
$routes->get('inprocess', 'Inprocess::index'); $routes->get('inprocess', 'Inprocess::index');
// Sales Invoice routes
$routes->get('invoicedetails/ViewInvoice', 'User::ViewInvoice');
$routes->get('getInvoiceAttachment', 'User::getInvoiceAttachment');
$routes->get('deleteAttachment', 'User::deleteAttachment');
$routes->post('saveAttachment', 'User::saveAttachment');

View File

@ -10,6 +10,8 @@ use App\Models\Costcenter_model;
use App\Models\Dashboard_model; use App\Models\Dashboard_model;
use App\Models\Employeedetails_model; use App\Models\Employeedetails_model;
use App\Models\User_model; use App\Models\User_model;
use App\Models\Ipinvoice_model;
use App\Models\Ipattachment_model;
use App\Models\Zohobooks_api_model; use App\Models\Zohobooks_api_model;
require_once 'vendor/autoload.php'; require_once 'vendor/autoload.php';
@ -27,6 +29,8 @@ class User extends BaseController
protected $dahsboard_Model; protected $dahsboard_Model;
protected $employeedetails_model; protected $employeedetails_model;
protected $user_model; protected $user_model;
protected $ipinvoice_model;
protected $ipattachment_model;
protected $session; protected $session;
/** /**
@ -40,6 +44,8 @@ class User extends BaseController
$this->costcenter_model = new Costcenter_model(); $this->costcenter_model = new Costcenter_model();
$this->employeedetails_model = new employeedetails_model(); $this->employeedetails_model = new employeedetails_model();
$this->user_model = new User_model(); $this->user_model = new User_model();
$this->ipinvoice_model = new Ipinvoice_model();
$this->ipattachment_model = new Ipattachment_model();
$this->session = session(); $this->session = session();
helper('form'); //$this->load->library('form_validation'); helper('form'); //$this->load->library('form_validation');
$this->isLoggedIn(); $this->isLoggedIn();
@ -1625,4 +1631,100 @@ class User extends BaseController
} }
} }
// END zoho API // END zoho API
// Sales Invoice List
function sales_invoice(){
$this->global['pageTitle'] = 'Sales Invoice';
$data['sales_invoice'] = $this->ipinvoice_model->saleInvoiceListing();
// echo "<pre>";
// print_r($data);die;
$this->loadViews("sales_invoice", $this->global, $data, NULL);
}
// Sales Invoice List
// Sales Invoice
function ViewInvoice($InvoiceNO = ''){
if ($InvoiceNO == '') {
$InvoiceID = $_GET['InvoiceID'];
} else {
$InvoiceID = $InvoiceNO;
}
$data['invoiceDetails'] = $this->ipinvoice_model->getInvoice($InvoiceID);
$data['invoiceAttachment'] = $this->ipinvoice_model->getinvoiceAttachment($InvoiceID);
// echo "<pre>";
// print_r($data);die;
$this->global['pageTitle'] = 'View Invoice';
$this->loadViews("editInvoice", $this->global, $data, NULL);
}
// Sales Invoice
// Sales Invoice
function getInvoiceAttachment(){
$data['invoiceAttachment'] = $this->ipinvoice_model->getinvoiceAttachment($this->request->getGet('invoice_number'));
return json_encode($data);
}
// Sales Invoice
// User Controller
function deleteAttachment() {
$invoice_attachment_id = $this->request->getGet('invoice_attachment_id'); // Get the attachment ID from the request
// Ensure ID is not empty
if ($invoice_attachment_id) {
// Load the model
// Call the model method to delete the attachment
$result = $this->ipinvoice_model->deleteAttachment($invoice_attachment_id);
if ($result) {
echo json_encode(['status' => 'success', 'message' => 'Attachment deleted successfully.']);
} else {
echo json_encode(['status' => 'error', 'message' => 'Failed to delete attachment.']);
}
} else {
echo json_encode(['status' => 'error', 'message' => 'Invalid attachment ID.']);
}
}
function saveAttachment() {
$invoiceId = $this->request->getPost('invoice_id');
$fileNames = $this->request->getPost('file_name[]');
$files = $this->request->getFiles();
if ($files && isset($files['emp_file']) && is_array($files['emp_file'])) {
foreach ($files['emp_file'] as $key => $file) {
if ($file->isValid() && !$file->hasMoved()) {
// Generate a unique name for the file
$newFileName = $file->getRandomName();
// Move the file to the target directory
$file->move('./public/uploads/images/invoice_files/', $newFileName);
// Insert the file info into the database
$data = [
'invoice_id' => $invoiceId,
'file_name' => $newFileName,
'attachment_name' => $fileNames[$key]
];
$this->ipattachment_model->addNewAttachment($data);
}
}
} else {
return $this->response->setJSON(['success' => false, 'message' => 'No files uploaded or incorrect input name.']);
}
return $this->response->setJSON(['success' => true]);
}
} }

View File

@ -77,7 +77,6 @@ if (! function_exists('getheringInvoiceDetails')) {
// Store headers and data // Store headers and data
$data['headers_new'] = $headers; $data['headers_new'] = $headers;
$data['data'] = curl_exec($ch); $data['data'] = curl_exec($ch);
// Return data // Return data
return $data; return $data;
} }

View File

@ -0,0 +1,78 @@
<?php
namespace App\Models;
use CodeIgniter\Model;
class Ipattachment_model extends Model
{
/**
* This function is used to add new user to system
* @return number $insert_id : This is last inserted id
*/
function addNewAttachment($attachments)
{
$this->db->transStart();
$builder = $this->db->table('ip_invoice_attachment');
$builder->insert($attachments);
$insert_id = $this->db->affectedRows();
$this->db->transComplete();
return $insert_id;
}
// Ipinvoice_model
public function deleteAttachment($invoice_attachment_id) {
// Get the attachment details to get the file path
$builder = $this->db->table('ip_invoice_attachment');
$builder->where('invoice_attachment_id', $invoice_attachment_id);
$query = $builder->get();
$attachment = $query->getRowArray(); // Get single row as an associative array
if ($attachment) {
// Construct the file path
$fileName = $attachment['attachment_name']; // Make sure this is the correct field name
$filePath = './public/uploads/images/invoice_files/' . $fileName;
// Debug: Log the file path
log_message('error', 'Attempting to delete file: ' . $filePath);
// Check if the path is actually a file
if (file_exists($filePath) && !is_dir($filePath)) {
unlink($filePath); // Delete the file
} else {
log_message('error', 'File does not exist or is a directory: ' . $filePath);
}
// Delete the record from the database
$builder->where('invoice_attachment_id', $invoice_attachment_id);
$builder->delete();
return $this->db->affectedRows() > 0;
}
return false;
}
}

View File

@ -0,0 +1,184 @@
<?php
namespace App\Models;
use CodeIgniter\Model;
class Ipinvoice_model extends Model
{
/**
* This function is used to get the user listing count
* @param string $searchText : This is optional search text
* @param number $page : This is pagination offset
* @param number $segment : This is pagination limit
* @return array $result : This is result
*/
function saleInvoiceListing()
{
$builder = $this->db->table('ip_invoices ')
->select('ip_invoices.invoice_id, ip_invoices.user_id, ip_invoices.client_id,
ip_invoices.invoice_group_id, ip_invoices.invoice_status_id, ip_invoices.invoice_date_due, ip_invoices.invoice_date_created,
ip_invoices.invoice_number, ip_invoices.invoice_terms, ip_clients.client_name,
ip_payment_methods.payment_method_name, ip_users.user_name, ip_products.product_name,
ip_invoice_amounts.invoice_total')
->join('ip_payment_methods', 'ip_invoices.payment_method = ip_payment_methods.payment_method_id', 'left')
->join('ip_clients', 'ip_invoices.client_id = ip_clients.client_id', 'left')
->join('ip_users', 'ip_invoices.user_id = ip_users.user_id', 'left')
->join('ip_invoice_items', 'ip_invoices.invoice_id = ip_invoice_items.invoice_id', 'left')
->join('ip_products', 'ip_invoice_items.item_product_id = ip_products.product_id', 'left')
->join('ip_invoice_amounts', 'ip_invoices.invoice_id = ip_invoice_amounts.invoice_id', 'left')
->orderBy('ip_invoices.invoice_number', 'DESC');
$query = $builder->get();
$result = $query->getResult();
return $result;
}
/**
* This function is used to add new user to system
* @return number $insert_id : This is last inserted id
*/
function addNewUser($userInfo)
{
$this->db->transStart();
$builder = $this->db->table('tbl_users');
$builder->insert($userInfo);
$insert_id = $this->db->affectedRows();
$this->db->transComplete();
return $insert_id;
}
/**
* This function used to get user information by id
* @param number $userId : This is user id
* @return array $result : This is user information
*/
function getInvoice($invoiceId)
{
$builder = $this->db->table('ip_invoices')
// ->select('')
->where('invoice_id', $invoiceId);
$query = $builder->get();
return $query->getResult();
}
/**
* This function used to get user information by id
* @param number $userId : This is user id
* @return array $result : This is user information
*/
function getinvoiceAttachment($invoiceId)
{
$builder = $this->db->table('ip_invoice_attachment')
// ->select('')
->where('invoice_id', $invoiceId);
$query = $builder->get();
return $query->getResult();
}
// Ipinvoice_model
public function deleteAttachment($invoice_attachment_id) {
// Get the attachment details to get the file path
$builder = $this->db->table('ip_invoice_attachment');
$builder->where('invoice_attachment_id', $invoice_attachment_id);
$query = $builder->get();
$attachment = $query->getRowArray(); // Get single row as an associative array
if ($attachment) {
// Construct the file path
$fileName = $attachment['attachment_name']; // Make sure this is the correct field name
$filePath = './public/uploads/images/invoice_files/' . $fileName;
// Debug: Log the file path
log_message('error', 'Attempting to delete file: ' . $filePath);
// Check if the path is actually a file
if (file_exists($filePath) && !is_dir($filePath)) {
unlink($filePath); // Delete the file
} else {
log_message('error', 'File does not exist or is a directory: ' . $filePath);
}
// Delete the record from the database
$builder->where('invoice_attachment_id', $invoice_attachment_id);
$builder->delete();
return $this->db->affectedRows() > 0;
}
return false;
}
/**
* This function is used to update the user information
* @param array $userInfo : This is users updated information
* @param number $userId : This is user id
*/
function editUser($userInfo, $userId)
{
$this->db->table('tbl_users')
->where('EmpID', $userId)
->update($userInfo);
return TRUE;
}
/**
* This function is used to delete the user information
* @param number $userId : This is user id
* @return boolean $result : TRUE / FALSE
*/
function deleteUser($userId, $userInfo)
{
$this->db->table('tbl_users')
->where('userId', $userId)
->update($userInfo);
return $this->db->affectedRows();
}
/**
* This function is used to get the All employees
* @return array $result : This is result of the query
*/
function getAllEmployees()
{
/*->select('EmpID,FirstName,LastName');
$builder = $this->db->table('t_employee_details');
$query = $builder->get();
return $query->getResult(); */
$builder = $this->db->table('t_employee_details EMP')
->select('EMP.EmpID,EMP.FirstName,EMP.LastName,EMP.Designation,EMP.EmailId,EMP.ContactNumber,DEPT.DEPCode,DEPT.DepartmentName')
->join('t_departmentdetails DEPT', 'EMP.Departmentcode = DEPT.DEPCode')
->where('EMP.IsActive ', 1);
$query = $builder->get();
return $query->getResult();
}
}

View File

@ -347,7 +347,11 @@
</li><!--Dashboard active treeview --> </li><!--Dashboard active treeview -->
<!-- Dashboard Ends --> <!-- Dashboard Ends -->
<?php } ?> <?php } ?>
<li class="treeview">
<a id="salesDashboardLin" href="<?php echo base_url(); ?>sales_invoice">
<i class="fa fa-file-text-o"></i><span>Sales Invoice</span>
</a>
</li><!--Dashboard active treeview -->
<?php if($DEPCode == ADMIN) { ?> <?php if($DEPCode == ADMIN) { ?>

305
app/Views/sales_invoice.php Normal file
View File

@ -0,0 +1,305 @@
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
<center>Sales Invoice</center>
</h1>
</section>
<section class="content">
<div class="row">
<div class="col-xs-12 text-right">
<div class="form-group">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-header">
</div><!-- /.box-header -->
<div class="box-body">
<table id="datatable_sales_invoice_list" class="table table-bordered table-hover" style="background-color:#fff;font-size:12px;text-align: right;" >
<thead style="background-color: #ddd;">
<tr >
<th width="10%">Invoice No</th>
<th width="10%">Invoice Date Created</th>
<th width="10%">Invoice Date Due</th>
<th width="10%">Client Name</th>
<th width="10%">User Name</th>
<th width="10%">Product Name</th>
<th width="10%" >Payment Method</th>
<th width="10%">Invoice Total</th>
</tr>
</thead>
<tbody>
<input type="text" id="invoice_id_set" name="invoice_id_set" hidden>
<?php if(!empty($sales_invoice)){ foreach($sales_invoice as $invoice){ ?>
<tr style="cursor: pointer;" onclick="openInvoiceModal('<?php echo $invoice->invoice_number; ?>')">
<td style="text-align: left;">
<?php echo $invoice->invoice_number; ?>
</td>
<td style="text-align: center;"><?php echo date('d/m/y', strtotime($invoice->invoice_date_created)); ?>
<td style="text-align: center;"><?php echo date('d/m/y', strtotime($invoice->invoice_date_due)); ?>
</td>
<td style="text-align: center;"><?php echo $invoice->client_name ?></td>
<td style="text-align: center;"><?php echo $invoice->user_name ?></td>
<td style="text-align: center;"><?php echo $invoice->product_name ?></td>
<td style="text-align: center;"><?php echo $invoice->payment_method_name; ?></td>
<td style="text-align: center;"><?php echo $invoice->invoice_total ?></td>
</tr>
<?php
}
}
?>
</tbody>
</table>
</div><!-- /.box-body -->
<!-- <div class="box-footer clearfix">
</div> -->
</div><!-- /.box -->
</div>
</div>
</section>
</div>
<!-- Modal Structure -->
<div class="modal fade" id="invoiceModal" tabindex="-1" role="dialog" aria-labelledby="invoiceModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="invoiceModalLabel">Invoice Files</h3>
<label for=""> Invoice Number :</label><span id="invoice_number_display_model"></span>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<div class="col-md-12">
<div class="col-md-10"></div>
<div class="col-md-2">
<button type="button" class="btn btn-primary btn-sm a1" onclick="appendFilesFileds()" id="day">
Add New File
</button>
</div>
</div>
</div>
<div class="modal-body" style="margin-top: 23px;">
<div id="filesContainer">
<!-- Rows will be dynamically appended here -->
</div>
<?php if(isset($invoice_data)){ foreach ($invoice_data as $key => $value) { ?>
<div class="col-md-12 pad ">
<div class="col-md-6">
<span>File Name</span>
<input type="text" maxlength="255" class="form-control"
value="<?php echo $value['file_name']; ?>" readonly>
</div>
<div class="col-md-1" style="margin-top: 25px;">
<a href="<?php echo base_url() . 'public/uploads/images/emp_files/' . $value['emp_file']; ?>"
download>
<i class="fa fa-download" aria-hidden="true"
style="font-size: 25px;"></i>
</a>
</div>
<div class="col-md-5" style="margin-top: 23px;">
<button type="button" class="btn btn-danger btn-sm"
id="<?= $value['id']; ?>"
onclick="removeContact(this)">Delete</button>
</div>
</div>
<?php } } ?>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" onclick="saveAttachment()" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="<?php echo base_url(); ?>public/assets/js/common.js" charset="utf-8"></script>
<script type="text/javascript">
$(function () {
$('#datatable_sales_invoice_list').DataTable({
"paging": true,
"lengthChange": true,
"searching": true,
"ordering": true,
"columnDefs": [{
"targets": 0,
"type": "date-eu"
}],
"aaSorting": [
[1, "desc"]
],
"info": true,
"autoWidth": true,
"pageLength": 10,
"lengthMenu": [10, 25, 50, 100],
});
});
</script>
<script>
function saveAttachment() {
var formData = new FormData();
var invoiceId = $('#invoice_id_set').val();
formData.append('invoice_id', invoiceId);
// Append files
$('input[name="emp_file[]"]').each(function(index, input) {
var files = $(input)[0].files;
if (files.length > 0) {
formData.append('emp_file[]', files[0]);
}
});
// Append other fields
$('input[name="file_name[]"]').each(function(index, input) {
formData.append('file_name[]', $(input).val());
});
// AJAX request using FormData
$.ajax({
url: '<?php echo base_url() ?>saveAttachment',
type: 'POST',
data: formData,
processData: false, // Prevent jQuery from converting the data
contentType: false, // Prevent jQuery from overriding the content type
success: function(response) {
console.log(response);
if (response.success) {
$('#invoiceModal').modal('hide');
// Handle success
} else {
alert(response.message);
}
},
error: function() {
alert('An error occurred while saving the attachment.');
}
});
}
function openInvoiceModal(invoiceNumber) {
$('#invoice_number_display_model').html(invoiceNumber);
// document.getElementById('modalInvoiceNumber').innerText = invoiceNumber;
$('#day').show();
// $('#invoiceModal').modal('show');
url:"<?php echo base_url() ?>servicepurchaseorder/getPODetails",
$('#invoice_id_set').val(invoiceNumber);
$.ajax({
url: '<?php echo base_url() ?>getInvoiceAttachment',
type: 'GET',
data: { invoice_number: invoiceNumber },
success: function(response) {
console.log(JSON.parse(response).invoiceAttachment);
var list = JSON.parse(response).invoiceAttachment;
var attachmentsHtml = '';
list.forEach(element => {
console.log(element);
var fileName = element.file_name;
var attachmentName = element.attachment_name;
attachmentsHtml += `
<div class="col-md-12 pad">
<div class="col-md-4">
<span>File Name</span>
<input type="text" maxlength="255" class="form-control"
value="${attachmentName}" readonly>
</div>
<div class="col-md-1" style="margin-top: 25px;">
<a href="<?php echo base_url() . 'public/uploads/images/invoice_files/' ?>${fileName}" download>
<i class="fa fa-download" aria-hidden="true"
style="font-size: 25px;"></i>
</a>
</div>
<div class="col-md-5" style="margin-top: 23px;">
<button type="button" class="btn btn-danger btn-sm"
id="${element.invoice_attachment_id}"
onclick="removeContact(this)">Delete</button>
</div>
</div>`;
});
$('#filesContainer').html(attachmentsHtml);
$('#invoiceModal').modal('show');
},
error: function() {
// Handle any errors during the AJAX request
$('#filesContainer').html('<p>There was an error loading the attachments.</p>');
$('#invoiceModal').modal('show');
}
});
}
function appendFilesFileds(data) {
var newRowHtml = `
<div class="col-md-12 pad">
<div class="col-md-4">
<span for="file_name">File name</span>
<input type="text" id="file_name" name="file_name[]" maxlength="255" class="form-control" value="${data != null && data != '' ? data.file_name : ''}">
</div>
<div class="col-md-4">
<span for="emp_file">File</span>
<input type="file" name="emp_file[]" class="form-control">
</div>
<div class="col-md-4" style="margin-top: 23px;">
<button type="button" class="btn btn-danger btn-sm" onclick="removeContact(this)">Remove</button>
<button type="button" class="btn btn-primary btn-sm a1" onclick="appendFilesFileds()">Add</button>
</div>
</div>`;
// Append the new row to the container
$('#filesContainer').append(newRowHtml);
// Hide all "Add" buttons except the last one
$('.a1').hide();
$('#filesContainer .pad:last .a1').show();
}
function removeContact(button) {
$(button).closest('.pad').remove();
$('#filesContainer .a1').hide();
$('#filesContainer .pad:last .a1').show();
var len = $('#filesContainer .pad:last .a1')
var length = len.length;
if (length == 0) {
$('#day').show()
} else {
$('#day').hide()
}
console.log("-------------------");
console.log(button);
console.log($(button).val());
console.log($(button).attr('id'));
$.ajax({
url: '<?php echo base_url() ?>deleteAttachment',
type: 'GET',
data: { invoice_attachment_id: $(button).attr('id') },
success: function(response) {
console.log(response);
},
error: function() {
}
});
}
</script>

View File

View File

@ -112,9 +112,8 @@ if (PHP_VERSION_ID < 80000) {
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
) { ) {
include("phpvfscomposer://" . __DIR__ . '/..'.'/friendsofphp/php-cs-fixer/php-cs-fixer'); return include("phpvfscomposer://" . __DIR__ . '/..'.'/friendsofphp/php-cs-fixer/php-cs-fixer');
exit(0);
} }
} }
include __DIR__ . '/..'.'/friendsofphp/php-cs-fixer/php-cs-fixer'; return include __DIR__ . '/..'.'/friendsofphp/php-cs-fixer/php-cs-fixer';

View File

@ -4,6 +4,12 @@ All notable changes to this library will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v1.8.1](https://github.com/CodeIgniter/coding-standard/compare/v1.8.0...v1.8.1) - 2024-08-05
- Add `keep_annotations` option for `php_unit_attributes`
- Add `php_unit_assert_new_names` fixer
- Bump dependencies
## [v1.8.0](https://github.com/CodeIgniter/coding-standard/compare/v1.7.16...v1.8.0) - 2024-06-16 ## [v1.8.0](https://github.com/CodeIgniter/coding-standard/compare/v1.7.16...v1.8.0) - 2024-06-16
- Enable rules for PHP 8.1 (#20) - Enable rules for PHP 8.1 (#20)

View File

@ -21,13 +21,13 @@
"require": { "require": {
"php": "^8.1", "php": "^8.1",
"ext-tokenizer": "*", "ext-tokenizer": "*",
"friendsofphp/php-cs-fixer": "^3.50", "friendsofphp/php-cs-fixer": "^3.61.1",
"nexusphp/cs-config": "^3.19.0" "nexusphp/cs-config": "^3.24"
}, },
"require-dev": { "require-dev": {
"nexusphp/tachycardia": "^2.1", "nexusphp/tachycardia": "^2.3",
"phpstan/phpstan": "^1.0", "phpstan/phpstan": "^1.11",
"phpunit/phpunit": "^10.5" "phpunit/phpunit": "^10.5 || ^11.2"
}, },
"minimum-stability": "dev", "minimum-stability": "dev",
"prefer-stable": true, "prefer-stable": true,

View File

@ -373,8 +373,11 @@ final class CodeIgniter4 extends AbstractRuleset
'sort_algorithm' => 'alpha', 'sort_algorithm' => 'alpha',
'case_sensitive' => false, 'case_sensitive' => false,
], ],
'php_unit_attributes' => true, 'php_unit_assert_new_names' => true,
'php_unit_construct' => [ 'php_unit_attributes' => [
'keep_annotations' => false,
],
'php_unit_construct' => [
'assertions' => [ 'assertions' => [
'assertSame', 'assertSame',
'assertEquals', 'assertEquals',

View File

@ -45,35 +45,34 @@ class ClassLoader
/** @var \Closure(string):void */ /** @var \Closure(string):void */
private static $includeFile; private static $includeFile;
/** @var ?string */ /** @var string|null */
private $vendorDir; private $vendorDir;
// PSR-4 // PSR-4
/** /**
* @var array[] * @var array<string, array<string, int>>
* @psalm-var array<string, array<string, int>>
*/ */
private $prefixLengthsPsr4 = array(); private $prefixLengthsPsr4 = array();
/** /**
* @var array[] * @var array<string, list<string>>
* @psalm-var array<string, array<int, string>>
*/ */
private $prefixDirsPsr4 = array(); private $prefixDirsPsr4 = array();
/** /**
* @var array[] * @var list<string>
* @psalm-var array<string, string>
*/ */
private $fallbackDirsPsr4 = array(); private $fallbackDirsPsr4 = array();
// PSR-0 // PSR-0
/** /**
* @var array[] * List of PSR-0 prefixes
* @psalm-var array<string, array<string, string[]>> *
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
*
* @var array<string, array<string, list<string>>>
*/ */
private $prefixesPsr0 = array(); private $prefixesPsr0 = array();
/** /**
* @var array[] * @var list<string>
* @psalm-var array<string, string>
*/ */
private $fallbackDirsPsr0 = array(); private $fallbackDirsPsr0 = array();
@ -81,8 +80,7 @@ class ClassLoader
private $useIncludePath = false; private $useIncludePath = false;
/** /**
* @var string[] * @var array<string, string>
* @psalm-var array<string, string>
*/ */
private $classMap = array(); private $classMap = array();
@ -90,21 +88,20 @@ class ClassLoader
private $classMapAuthoritative = false; private $classMapAuthoritative = false;
/** /**
* @var bool[] * @var array<string, bool>
* @psalm-var array<string, bool>
*/ */
private $missingClasses = array(); private $missingClasses = array();
/** @var ?string */ /** @var string|null */
private $apcuPrefix; private $apcuPrefix;
/** /**
* @var self[] * @var array<string, self>
*/ */
private static $registeredLoaders = array(); private static $registeredLoaders = array();
/** /**
* @param ?string $vendorDir * @param string|null $vendorDir
*/ */
public function __construct($vendorDir = null) public function __construct($vendorDir = null)
{ {
@ -113,7 +110,7 @@ class ClassLoader
} }
/** /**
* @return string[] * @return array<string, list<string>>
*/ */
public function getPrefixes() public function getPrefixes()
{ {
@ -125,8 +122,7 @@ class ClassLoader
} }
/** /**
* @return array[] * @return array<string, list<string>>
* @psalm-return array<string, array<int, string>>
*/ */
public function getPrefixesPsr4() public function getPrefixesPsr4()
{ {
@ -134,8 +130,7 @@ class ClassLoader
} }
/** /**
* @return array[] * @return list<string>
* @psalm-return array<string, string>
*/ */
public function getFallbackDirs() public function getFallbackDirs()
{ {
@ -143,8 +138,7 @@ class ClassLoader
} }
/** /**
* @return array[] * @return list<string>
* @psalm-return array<string, string>
*/ */
public function getFallbackDirsPsr4() public function getFallbackDirsPsr4()
{ {
@ -152,8 +146,7 @@ class ClassLoader
} }
/** /**
* @return string[] Array of classname => path * @return array<string, string> Array of classname => path
* @psalm-return array<string, string>
*/ */
public function getClassMap() public function getClassMap()
{ {
@ -161,8 +154,7 @@ class ClassLoader
} }
/** /**
* @param string[] $classMap Class to filename map * @param array<string, string> $classMap Class to filename map
* @psalm-param array<string, string> $classMap
* *
* @return void * @return void
*/ */
@ -179,24 +171,25 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, either * Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix. * appending or prepending to the ones previously set for this prefix.
* *
* @param string $prefix The prefix * @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories * @param list<string>|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories * @param bool $prepend Whether to prepend the directories
* *
* @return void * @return void
*/ */
public function add($prefix, $paths, $prepend = false) public function add($prefix, $paths, $prepend = false)
{ {
$paths = (array) $paths;
if (!$prefix) { if (!$prefix) {
if ($prepend) { if ($prepend) {
$this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0 = array_merge(
(array) $paths, $paths,
$this->fallbackDirsPsr0 $this->fallbackDirsPsr0
); );
} else { } else {
$this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0, $this->fallbackDirsPsr0,
(array) $paths $paths
); );
} }
@ -205,19 +198,19 @@ class ClassLoader
$first = $prefix[0]; $first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) { if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths; $this->prefixesPsr0[$first][$prefix] = $paths;
return; return;
} }
if ($prepend) { if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths, $paths,
$this->prefixesPsr0[$first][$prefix] $this->prefixesPsr0[$first][$prefix]
); );
} else { } else {
$this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix], $this->prefixesPsr0[$first][$prefix],
(array) $paths $paths
); );
} }
} }
@ -226,9 +219,9 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, either * Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace. * appending or prepending to the ones previously set for this namespace.
* *
* @param string $prefix The prefix/namespace, with trailing '\\' * @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories * @param list<string>|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories * @param bool $prepend Whether to prepend the directories
* *
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
* *
@ -236,17 +229,18 @@ class ClassLoader
*/ */
public function addPsr4($prefix, $paths, $prepend = false) public function addPsr4($prefix, $paths, $prepend = false)
{ {
$paths = (array) $paths;
if (!$prefix) { if (!$prefix) {
// Register directories for the root namespace. // Register directories for the root namespace.
if ($prepend) { if ($prepend) {
$this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4 = array_merge(
(array) $paths, $paths,
$this->fallbackDirsPsr4 $this->fallbackDirsPsr4
); );
} else { } else {
$this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4, $this->fallbackDirsPsr4,
(array) $paths $paths
); );
} }
} elseif (!isset($this->prefixDirsPsr4[$prefix])) { } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@ -256,18 +250,18 @@ class ClassLoader
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
} }
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths; $this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) { } elseif ($prepend) {
// Prepend directories for an already registered namespace. // Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths, $paths,
$this->prefixDirsPsr4[$prefix] $this->prefixDirsPsr4[$prefix]
); );
} else { } else {
// Append directories for an already registered namespace. // Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix], $this->prefixDirsPsr4[$prefix],
(array) $paths $paths
); );
} }
} }
@ -276,8 +270,8 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, * Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix. * replacing any others previously set for this prefix.
* *
* @param string $prefix The prefix * @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories * @param list<string>|string $paths The PSR-0 base directories
* *
* @return void * @return void
*/ */
@ -294,8 +288,8 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, * Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace. * replacing any others previously set for this namespace.
* *
* @param string $prefix The prefix/namespace, with trailing '\\' * @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories * @param list<string>|string $paths The PSR-4 base directories
* *
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
* *
@ -429,7 +423,8 @@ class ClassLoader
public function loadClass($class) public function loadClass($class)
{ {
if ($file = $this->findFile($class)) { if ($file = $this->findFile($class)) {
(self::$includeFile)($file); $includeFile = self::$includeFile;
$includeFile($file);
return true; return true;
} }
@ -480,9 +475,9 @@ class ClassLoader
} }
/** /**
* Returns the currently registered loaders indexed by their corresponding vendor directories. * Returns the currently registered loaders keyed by their corresponding vendor directories.
* *
* @return self[] * @return array<string, self>
*/ */
public static function getRegisteredLoaders() public static function getRegisteredLoaders()
{ {
@ -560,7 +555,10 @@ class ClassLoader
return false; return false;
} }
private static function initializeIncludeClosure(): void /**
* @return void
*/
private static function initializeIncludeClosure()
{ {
if (self::$includeFile !== null) { if (self::$includeFile !== null) {
return; return;
@ -574,8 +572,8 @@ class ClassLoader
* @param string $file * @param string $file
* @return void * @return void
*/ */
self::$includeFile = static function($file) { self::$includeFile = \Closure::bind(static function($file) {
include $file; include $file;
}; }, null, null);
} }
} }

View File

@ -98,7 +98,7 @@ class InstalledVersions
{ {
foreach (self::getInstalled() as $installed) { foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) { if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']); return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
} }
} }
@ -119,7 +119,7 @@ class InstalledVersions
*/ */
public static function satisfies(VersionParser $parser, $packageName, $constraint) public static function satisfies(VersionParser $parser, $packageName, $constraint)
{ {
$constraint = $parser->parseConstraints($constraint); $constraint = $parser->parseConstraints((string) $constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName)); $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint); return $provided->matches($constraint);
@ -328,7 +328,9 @@ class InstalledVersions
if (isset(self::$installedByVendor[$vendorDir])) { if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir]; $installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) { } elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php'; /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require $vendorDir.'/composer/installed.php';
$installed[] = self::$installedByVendor[$vendorDir] = $required;
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1]; self::$installed = $installed[count($installed) - 1];
} }
@ -340,12 +342,17 @@ class InstalledVersions
// only require the installed.php file if this file is loaded from its dumped location, // only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') { if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = require __DIR__ . '/installed.php'; /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require __DIR__ . '/installed.php';
self::$installed = $required;
} else { } else {
self::$installed = array(); self::$installed = array();
} }
} }
$installed[] = self::$installed;
if (self::$installed !== array()) {
$installed[] = self::$installed;
}
return $installed; return $installed;
} }

View File

@ -417,6 +417,11 @@ return array(
'Composer\\Pcre\\MatchResult' => $vendorDir . '/composer/pcre/src/MatchResult.php', 'Composer\\Pcre\\MatchResult' => $vendorDir . '/composer/pcre/src/MatchResult.php',
'Composer\\Pcre\\MatchStrictGroupsResult' => $vendorDir . '/composer/pcre/src/MatchStrictGroupsResult.php', 'Composer\\Pcre\\MatchStrictGroupsResult' => $vendorDir . '/composer/pcre/src/MatchStrictGroupsResult.php',
'Composer\\Pcre\\MatchWithOffsetsResult' => $vendorDir . '/composer/pcre/src/MatchWithOffsetsResult.php', 'Composer\\Pcre\\MatchWithOffsetsResult' => $vendorDir . '/composer/pcre/src/MatchWithOffsetsResult.php',
'Composer\\Pcre\\PHPStan\\InvalidRegexPatternRule' => $vendorDir . '/composer/pcre/src/PHPStan/InvalidRegexPatternRule.php',
'Composer\\Pcre\\PHPStan\\PregMatchFlags' => $vendorDir . '/composer/pcre/src/PHPStan/PregMatchFlags.php',
'Composer\\Pcre\\PHPStan\\PregMatchParameterOutTypeExtension' => $vendorDir . '/composer/pcre/src/PHPStan/PregMatchParameterOutTypeExtension.php',
'Composer\\Pcre\\PHPStan\\PregMatchTypeSpecifyingExtension' => $vendorDir . '/composer/pcre/src/PHPStan/PregMatchTypeSpecifyingExtension.php',
'Composer\\Pcre\\PHPStan\\UnsafeStrictGroupsCallRule' => $vendorDir . '/composer/pcre/src/PHPStan/UnsafeStrictGroupsCallRule.php',
'Composer\\Pcre\\PcreException' => $vendorDir . '/composer/pcre/src/PcreException.php', 'Composer\\Pcre\\PcreException' => $vendorDir . '/composer/pcre/src/PcreException.php',
'Composer\\Pcre\\Preg' => $vendorDir . '/composer/pcre/src/Preg.php', 'Composer\\Pcre\\Preg' => $vendorDir . '/composer/pcre/src/Preg.php',
'Composer\\Pcre\\Regex' => $vendorDir . '/composer/pcre/src/Regex.php', 'Composer\\Pcre\\Regex' => $vendorDir . '/composer/pcre/src/Regex.php',
@ -2620,6 +2625,7 @@ return array(
'PhpCsFixer\\Fixer\\PhpTag\\FullOpeningTagFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/FullOpeningTagFixer.php', 'PhpCsFixer\\Fixer\\PhpTag\\FullOpeningTagFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/FullOpeningTagFixer.php',
'PhpCsFixer\\Fixer\\PhpTag\\LinebreakAfterOpeningTagFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php', 'PhpCsFixer\\Fixer\\PhpTag\\LinebreakAfterOpeningTagFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php',
'PhpCsFixer\\Fixer\\PhpTag\\NoClosingTagFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoClosingTagFixer.php', 'PhpCsFixer\\Fixer\\PhpTag\\NoClosingTagFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoClosingTagFixer.php',
'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitAssertNewNamesFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitAssertNewNamesFixer.php',
'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitAttributesFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitAttributesFixer.php', 'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitAttributesFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitAttributesFixer.php',
'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitConstructFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitConstructFixer.php', 'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitConstructFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitConstructFixer.php',
'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitDataProviderNameFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDataProviderNameFixer.php', 'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitDataProviderNameFixer' => $vendorDir . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDataProviderNameFixer.php',
@ -2784,6 +2790,7 @@ return array(
'PhpCsFixer\\RuleSet\\Sets\\PHPUnit60MigrationRiskySet' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php', 'PhpCsFixer\\RuleSet\\Sets\\PHPUnit60MigrationRiskySet' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php',
'PhpCsFixer\\RuleSet\\Sets\\PHPUnit75MigrationRiskySet' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php', 'PhpCsFixer\\RuleSet\\Sets\\PHPUnit75MigrationRiskySet' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php',
'PhpCsFixer\\RuleSet\\Sets\\PHPUnit84MigrationRiskySet' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php', 'PhpCsFixer\\RuleSet\\Sets\\PHPUnit84MigrationRiskySet' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php',
'PhpCsFixer\\RuleSet\\Sets\\PHPUnit91MigrationRiskySet' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit91MigrationRiskySet.php',
'PhpCsFixer\\RuleSet\\Sets\\PSR12RiskySet' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12RiskySet.php', 'PhpCsFixer\\RuleSet\\Sets\\PSR12RiskySet' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12RiskySet.php',
'PhpCsFixer\\RuleSet\\Sets\\PSR12Set' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12Set.php', 'PhpCsFixer\\RuleSet\\Sets\\PSR12Set' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12Set.php',
'PhpCsFixer\\RuleSet\\Sets\\PSR1Set' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR1Set.php', 'PhpCsFixer\\RuleSet\\Sets\\PSR1Set' => $vendorDir . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR1Set.php',
@ -4648,6 +4655,7 @@ return array(
'Symfony\\Component\\Process\\Exception\\LogicException' => $vendorDir . '/symfony/process/Exception/LogicException.php', 'Symfony\\Component\\Process\\Exception\\LogicException' => $vendorDir . '/symfony/process/Exception/LogicException.php',
'Symfony\\Component\\Process\\Exception\\ProcessFailedException' => $vendorDir . '/symfony/process/Exception/ProcessFailedException.php', 'Symfony\\Component\\Process\\Exception\\ProcessFailedException' => $vendorDir . '/symfony/process/Exception/ProcessFailedException.php',
'Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => $vendorDir . '/symfony/process/Exception/ProcessSignaledException.php', 'Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => $vendorDir . '/symfony/process/Exception/ProcessSignaledException.php',
'Symfony\\Component\\Process\\Exception\\ProcessStartFailedException' => $vendorDir . '/symfony/process/Exception/ProcessStartFailedException.php',
'Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => $vendorDir . '/symfony/process/Exception/ProcessTimedOutException.php', 'Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => $vendorDir . '/symfony/process/Exception/ProcessTimedOutException.php',
'Symfony\\Component\\Process\\Exception\\RunProcessFailedException' => $vendorDir . '/symfony/process/Exception/RunProcessFailedException.php', 'Symfony\\Component\\Process\\Exception\\RunProcessFailedException' => $vendorDir . '/symfony/process/Exception/RunProcessFailedException.php',
'Symfony\\Component\\Process\\Exception\\RuntimeException' => $vendorDir . '/symfony/process/Exception/RuntimeException.php', 'Symfony\\Component\\Process\\Exception\\RuntimeException' => $vendorDir . '/symfony/process/Exception/RuntimeException.php',
@ -4688,9 +4696,7 @@ return array(
'Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php', 'Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php',
'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/symfony/service-contracts/Attribute/SubscribedService.php', 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/symfony/service-contracts/Attribute/SubscribedService.php',
'Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php', 'Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php',
'Symfony\\Contracts\\Service\\ServiceCollectionInterface' => $vendorDir . '/symfony/service-contracts/ServiceCollectionInterface.php',
'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php', 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php',
'Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php',
'Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php', 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php',
'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php',
'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php',

View File

@ -7,8 +7,8 @@ $baseDir = dirname($vendorDir);
return array( return array(
'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php', 'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',

View File

@ -34,15 +34,15 @@ class ComposerAutoloaderInitc8496d4dbcc79fa0e3d8c5678a3ba3c2
$loader->register(true); $loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticInitc8496d4dbcc79fa0e3d8c5678a3ba3c2::$files; $filesToLoad = \Composer\Autoload\ComposerStaticInitc8496d4dbcc79fa0e3d8c5678a3ba3c2::$files;
$requireFile = static function ($fileIdentifier, $file) { $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
require $file; require $file;
} }
}; }, null, null);
foreach ($filesToLoad as $fileIdentifier => $file) { foreach ($filesToLoad as $fileIdentifier => $file) {
($requireFile)($fileIdentifier, $file); $requireFile($fileIdentifier, $file);
} }
return $loader; return $loader;

View File

@ -8,8 +8,8 @@ class ComposerStaticInitc8496d4dbcc79fa0e3d8c5678a3ba3c2
{ {
public static $files = array ( public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php', 'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
@ -755,6 +755,11 @@ class ComposerStaticInitc8496d4dbcc79fa0e3d8c5678a3ba3c2
'Composer\\Pcre\\MatchResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchResult.php', 'Composer\\Pcre\\MatchResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchResult.php',
'Composer\\Pcre\\MatchStrictGroupsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchStrictGroupsResult.php', 'Composer\\Pcre\\MatchStrictGroupsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchStrictGroupsResult.php',
'Composer\\Pcre\\MatchWithOffsetsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchWithOffsetsResult.php', 'Composer\\Pcre\\MatchWithOffsetsResult' => __DIR__ . '/..' . '/composer/pcre/src/MatchWithOffsetsResult.php',
'Composer\\Pcre\\PHPStan\\InvalidRegexPatternRule' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/InvalidRegexPatternRule.php',
'Composer\\Pcre\\PHPStan\\PregMatchFlags' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/PregMatchFlags.php',
'Composer\\Pcre\\PHPStan\\PregMatchParameterOutTypeExtension' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/PregMatchParameterOutTypeExtension.php',
'Composer\\Pcre\\PHPStan\\PregMatchTypeSpecifyingExtension' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/PregMatchTypeSpecifyingExtension.php',
'Composer\\Pcre\\PHPStan\\UnsafeStrictGroupsCallRule' => __DIR__ . '/..' . '/composer/pcre/src/PHPStan/UnsafeStrictGroupsCallRule.php',
'Composer\\Pcre\\PcreException' => __DIR__ . '/..' . '/composer/pcre/src/PcreException.php', 'Composer\\Pcre\\PcreException' => __DIR__ . '/..' . '/composer/pcre/src/PcreException.php',
'Composer\\Pcre\\Preg' => __DIR__ . '/..' . '/composer/pcre/src/Preg.php', 'Composer\\Pcre\\Preg' => __DIR__ . '/..' . '/composer/pcre/src/Preg.php',
'Composer\\Pcre\\Regex' => __DIR__ . '/..' . '/composer/pcre/src/Regex.php', 'Composer\\Pcre\\Regex' => __DIR__ . '/..' . '/composer/pcre/src/Regex.php',
@ -2958,6 +2963,7 @@ class ComposerStaticInitc8496d4dbcc79fa0e3d8c5678a3ba3c2
'PhpCsFixer\\Fixer\\PhpTag\\FullOpeningTagFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/FullOpeningTagFixer.php', 'PhpCsFixer\\Fixer\\PhpTag\\FullOpeningTagFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/FullOpeningTagFixer.php',
'PhpCsFixer\\Fixer\\PhpTag\\LinebreakAfterOpeningTagFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php', 'PhpCsFixer\\Fixer\\PhpTag\\LinebreakAfterOpeningTagFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/LinebreakAfterOpeningTagFixer.php',
'PhpCsFixer\\Fixer\\PhpTag\\NoClosingTagFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoClosingTagFixer.php', 'PhpCsFixer\\Fixer\\PhpTag\\NoClosingTagFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpTag/NoClosingTagFixer.php',
'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitAssertNewNamesFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitAssertNewNamesFixer.php',
'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitAttributesFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitAttributesFixer.php', 'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitAttributesFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitAttributesFixer.php',
'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitConstructFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitConstructFixer.php', 'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitConstructFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitConstructFixer.php',
'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitDataProviderNameFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDataProviderNameFixer.php', 'PhpCsFixer\\Fixer\\PhpUnit\\PhpUnitDataProviderNameFixer' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/Fixer/PhpUnit/PhpUnitDataProviderNameFixer.php',
@ -3122,6 +3128,7 @@ class ComposerStaticInitc8496d4dbcc79fa0e3d8c5678a3ba3c2
'PhpCsFixer\\RuleSet\\Sets\\PHPUnit60MigrationRiskySet' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php', 'PhpCsFixer\\RuleSet\\Sets\\PHPUnit60MigrationRiskySet' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit60MigrationRiskySet.php',
'PhpCsFixer\\RuleSet\\Sets\\PHPUnit75MigrationRiskySet' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php', 'PhpCsFixer\\RuleSet\\Sets\\PHPUnit75MigrationRiskySet' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit75MigrationRiskySet.php',
'PhpCsFixer\\RuleSet\\Sets\\PHPUnit84MigrationRiskySet' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php', 'PhpCsFixer\\RuleSet\\Sets\\PHPUnit84MigrationRiskySet' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit84MigrationRiskySet.php',
'PhpCsFixer\\RuleSet\\Sets\\PHPUnit91MigrationRiskySet' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PHPUnit91MigrationRiskySet.php',
'PhpCsFixer\\RuleSet\\Sets\\PSR12RiskySet' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12RiskySet.php', 'PhpCsFixer\\RuleSet\\Sets\\PSR12RiskySet' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12RiskySet.php',
'PhpCsFixer\\RuleSet\\Sets\\PSR12Set' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12Set.php', 'PhpCsFixer\\RuleSet\\Sets\\PSR12Set' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR12Set.php',
'PhpCsFixer\\RuleSet\\Sets\\PSR1Set' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR1Set.php', 'PhpCsFixer\\RuleSet\\Sets\\PSR1Set' => __DIR__ . '/..' . '/friendsofphp/php-cs-fixer/src/RuleSet/Sets/PSR1Set.php',
@ -4986,6 +4993,7 @@ class ComposerStaticInitc8496d4dbcc79fa0e3d8c5678a3ba3c2
'Symfony\\Component\\Process\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/process/Exception/LogicException.php', 'Symfony\\Component\\Process\\Exception\\LogicException' => __DIR__ . '/..' . '/symfony/process/Exception/LogicException.php',
'Symfony\\Component\\Process\\Exception\\ProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessFailedException.php', 'Symfony\\Component\\Process\\Exception\\ProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessFailedException.php',
'Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessSignaledException.php', 'Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessSignaledException.php',
'Symfony\\Component\\Process\\Exception\\ProcessStartFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessStartFailedException.php',
'Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessTimedOutException.php', 'Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => __DIR__ . '/..' . '/symfony/process/Exception/ProcessTimedOutException.php',
'Symfony\\Component\\Process\\Exception\\RunProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/RunProcessFailedException.php', 'Symfony\\Component\\Process\\Exception\\RunProcessFailedException' => __DIR__ . '/..' . '/symfony/process/Exception/RunProcessFailedException.php',
'Symfony\\Component\\Process\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/process/Exception/RuntimeException.php', 'Symfony\\Component\\Process\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/process/Exception/RuntimeException.php',
@ -5026,9 +5034,7 @@ class ComposerStaticInitc8496d4dbcc79fa0e3d8c5678a3ba3c2
'Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php', 'Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php',
'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/SubscribedService.php', 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/SubscribedService.php',
'Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php', 'Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php',
'Symfony\\Contracts\\Service\\ServiceCollectionInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceCollectionInterface.php',
'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php', 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php',
'Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php',
'Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php', 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php',
'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php',
'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php',

View File

@ -69,31 +69,31 @@
}, },
{ {
"name": "codeigniter/coding-standard", "name": "codeigniter/coding-standard",
"version": "v1.8.0", "version": "v1.8.1",
"version_normalized": "1.8.0.0", "version_normalized": "1.8.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/CodeIgniter/coding-standard.git", "url": "https://github.com/CodeIgniter/coding-standard.git",
"reference": "a523fd030be6360123a88655f39f0eb1650ee4bf" "reference": "2c16682b4a3754bc6694fef1056f686f32298ee3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/CodeIgniter/coding-standard/zipball/a523fd030be6360123a88655f39f0eb1650ee4bf", "url": "https://api.github.com/repos/CodeIgniter/coding-standard/zipball/2c16682b4a3754bc6694fef1056f686f32298ee3",
"reference": "a523fd030be6360123a88655f39f0eb1650ee4bf", "reference": "2c16682b4a3754bc6694fef1056f686f32298ee3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-tokenizer": "*", "ext-tokenizer": "*",
"friendsofphp/php-cs-fixer": "^3.50", "friendsofphp/php-cs-fixer": "^3.61.1",
"nexusphp/cs-config": "^3.19.0", "nexusphp/cs-config": "^3.24",
"php": "^8.1" "php": "^8.1"
}, },
"require-dev": { "require-dev": {
"nexusphp/tachycardia": "^2.1", "nexusphp/tachycardia": "^2.3",
"phpstan/phpstan": "^1.0", "phpstan/phpstan": "^1.11",
"phpunit/phpunit": "^10.5" "phpunit/phpunit": "^10.5 || ^11.2"
}, },
"time": "2024-06-16T15:51:42+00:00", "time": "2024-08-05T11:17:44+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -126,32 +126,40 @@
}, },
{ {
"name": "composer/pcre", "name": "composer/pcre",
"version": "3.1.4", "version": "3.2.0",
"version_normalized": "3.1.4.0", "version_normalized": "3.2.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/pcre.git", "url": "https://github.com/composer/pcre.git",
"reference": "04229f163664973f68f38f6f73d917799168ef24" "reference": "ea4ab6f9580a4fd221e0418f2c357cdd39102a90"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/04229f163664973f68f38f6f73d917799168ef24", "url": "https://api.github.com/repos/composer/pcre/zipball/ea4ab6f9580a4fd221e0418f2c357cdd39102a90",
"reference": "04229f163664973f68f38f6f73d917799168ef24", "reference": "ea4ab6f9580a4fd221e0418f2c357cdd39102a90",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.4 || ^8.0" "php": "^7.4 || ^8.0"
}, },
"require-dev": { "conflict": {
"phpstan/phpstan": "^1.3", "phpstan/phpstan": "<1.11.8"
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^5"
}, },
"time": "2024-05-27T13:40:54+00:00", "require-dev": {
"phpstan/phpstan": "^1.11.8",
"phpstan/phpstan-strict-rules": "^1.1",
"phpunit/phpunit": "^8 || ^9"
},
"time": "2024-07-25T09:36:02+00:00",
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "3.x-dev" "dev-main": "3.x-dev"
},
"phpstan": {
"includes": [
"extension.neon"
]
} }
}, },
"installation-source": "dist", "installation-source": "dist",
@ -180,7 +188,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/composer/pcre/issues", "issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.1.4" "source": "https://github.com/composer/pcre/tree/3.2.0"
}, },
"funding": [ "funding": [
{ {
@ -533,17 +541,17 @@
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
"version": "v3.59.3", "version": "v3.62.0",
"version_normalized": "3.59.3.0", "version_normalized": "3.62.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "30ba9ecc2b0e5205e578fe29973c15653d9bfd29" "reference": "627692f794d35c43483f34b01d94740df2a73507"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/30ba9ecc2b0e5205e578fe29973c15653d9bfd29", "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/627692f794d35c43483f34b01d94740df2a73507",
"reference": "30ba9ecc2b0e5205e578fe29973c15653d9bfd29", "reference": "627692f794d35c43483f34b01d94740df2a73507",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -590,7 +598,7 @@
"ext-dom": "For handling output formats in XML", "ext-dom": "For handling output formats in XML",
"ext-mbstring": "For handling non-UTF8 characters." "ext-mbstring": "For handling non-UTF8 characters."
}, },
"time": "2024-06-16T14:17:03+00:00", "time": "2024-08-07T17:03:09+00:00",
"bin": [ "bin": [
"php-cs-fixer" "php-cs-fixer"
], ],
@ -627,7 +635,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.59.3" "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.62.0"
}, },
"funding": [ "funding": [
{ {
@ -1268,22 +1276,22 @@
}, },
{ {
"name": "nexusphp/cs-config", "name": "nexusphp/cs-config",
"version": "v3.23.1", "version": "v3.24.0",
"version_normalized": "3.23.1.0", "version_normalized": "3.24.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/NexusPHP/cs-config.git", "url": "https://github.com/NexusPHP/cs-config.git",
"reference": "323c8ca9c86a85d8cf9990e95079a7734bfbf4e6" "reference": "fd0fdb458cbf42ba636a2ed218530b335421f33f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/NexusPHP/cs-config/zipball/323c8ca9c86a85d8cf9990e95079a7734bfbf4e6", "url": "https://api.github.com/repos/NexusPHP/cs-config/zipball/fd0fdb458cbf42ba636a2ed218530b335421f33f",
"reference": "323c8ca9c86a85d8cf9990e95079a7734bfbf4e6", "reference": "fd0fdb458cbf42ba636a2ed218530b335421f33f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-tokenizer": "*", "ext-tokenizer": "*",
"friendsofphp/php-cs-fixer": "^3.57.1", "friendsofphp/php-cs-fixer": "^3.60",
"php": "^8.1" "php": "^8.1"
}, },
"conflict": { "conflict": {
@ -1297,13 +1305,8 @@
"phpstan/phpstan-strict-rules": "^1.5", "phpstan/phpstan-strict-rules": "^1.5",
"phpunit/phpunit": "^10.5 || ^11.0" "phpunit/phpunit": "^10.5 || ^11.0"
}, },
"time": "2024-06-16T15:46:10+00:00", "time": "2024-07-28T15:59:18+00:00",
"type": "library", "type": "library",
"extra": {
"branch-alias": {
"dev-develop": "3.x-dev"
}
},
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@ -1568,17 +1571,17 @@
}, },
{ {
"name": "phpoffice/phpspreadsheet", "name": "phpoffice/phpspreadsheet",
"version": "2.2.0", "version": "2.2.2",
"version_normalized": "2.2.0.0", "version_normalized": "2.2.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "b0993b7e4d9c860133365d115b176bc6e0f57022" "reference": "ffbcee68069b073bff07a71eb321dcd9f2763513"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/b0993b7e4d9c860133365d115b176bc6e0f57022", "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/ffbcee68069b073bff07a71eb321dcd9f2763513",
"reference": "b0993b7e4d9c860133365d115b176bc6e0f57022", "reference": "ffbcee68069b073bff07a71eb321dcd9f2763513",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1623,7 +1626,7 @@
"mpdf/mpdf": "Option for rendering PDF with PDF Writer", "mpdf/mpdf": "Option for rendering PDF with PDF Writer",
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
}, },
"time": "2024-07-24T13:21:18+00:00", "time": "2024-08-08T02:31:26+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -1669,7 +1672,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/2.2.0" "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/2.2.2"
}, },
"install-path": "../phpoffice/phpspreadsheet" "install-path": "../phpoffice/phpspreadsheet"
}, },
@ -2011,17 +2014,17 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "10.5.28", "version": "10.5.29",
"version_normalized": "10.5.28.0", "version_normalized": "10.5.29.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "ff7fb85cdf88131b83e721fb2a327b664dbed275" "reference": "8e9e80872b4e8064401788ee8a32d40b4455318f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ff7fb85cdf88131b83e721fb2a327b664dbed275", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e9e80872b4e8064401788ee8a32d40b4455318f",
"reference": "ff7fb85cdf88131b83e721fb2a327b664dbed275", "reference": "8e9e80872b4e8064401788ee8a32d40b4455318f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2055,7 +2058,7 @@
"suggest": { "suggest": {
"ext-soap": "To be able to generate mocks based on WSDL files" "ext-soap": "To be able to generate mocks based on WSDL files"
}, },
"time": "2024-07-18T14:54:16+00:00", "time": "2024-07-30T11:08:00+00:00",
"bin": [ "bin": [
"phpunit" "phpunit"
], ],
@ -2095,7 +2098,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy", "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.28" "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.29"
}, },
"funding": [ "funding": [
{ {
@ -2951,34 +2954,34 @@
}, },
{ {
"name": "react/socket", "name": "react/socket",
"version": "v1.15.0", "version": "v1.16.0",
"version_normalized": "1.15.0.0", "version_normalized": "1.16.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/reactphp/socket.git", "url": "https://github.com/reactphp/socket.git",
"reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038" "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/reactphp/socket/zipball/216d3aec0b87f04a40ca04f481e6af01bdd1d038", "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1",
"reference": "216d3aec0b87f04a40ca04f481e6af01bdd1d038", "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"evenement/evenement": "^3.0 || ^2.0 || ^1.0", "evenement/evenement": "^3.0 || ^2.0 || ^1.0",
"php": ">=5.3.0", "php": ">=5.3.0",
"react/dns": "^1.11", "react/dns": "^1.13",
"react/event-loop": "^1.2", "react/event-loop": "^1.2",
"react/promise": "^3 || ^2.6 || ^1.2.1", "react/promise": "^3.2 || ^2.6 || ^1.2.1",
"react/stream": "^1.2" "react/stream": "^1.4"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36",
"react/async": "^4 || ^3 || ^2", "react/async": "^4.3 || ^3.3 || ^2",
"react/promise-stream": "^1.4", "react/promise-stream": "^1.4",
"react/promise-timer": "^1.10" "react/promise-timer": "^1.11"
}, },
"time": "2023-12-15T11:02:10+00:00", "time": "2024-07-26T10:38:09+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -3022,7 +3025,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/reactphp/socket/issues", "issues": "https://github.com/reactphp/socket/issues",
"source": "https://github.com/reactphp/socket/tree/v1.15.0" "source": "https://github.com/reactphp/socket/tree/v1.16.0"
}, },
"funding": [ "funding": [
{ {
@ -3292,17 +3295,17 @@
}, },
{ {
"name": "sebastian/comparator", "name": "sebastian/comparator",
"version": "5.0.1", "version": "5.0.2",
"version_normalized": "5.0.1.0", "version_normalized": "5.0.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git", "url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "2db5010a484d53ebf536087a70b4a5423c102372" "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53",
"reference": "2db5010a484d53ebf536087a70b4a5423c102372", "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3313,9 +3316,9 @@
"sebastian/exporter": "^5.0" "sebastian/exporter": "^5.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^10.3" "phpunit/phpunit": "^10.4"
}, },
"time": "2023-08-14T13:18:12+00:00", "time": "2024-08-12T06:03:08+00:00",
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
@ -3360,7 +3363,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues", "issues": "https://github.com/sebastianbergmann/comparator/issues",
"security": "https://github.com/sebastianbergmann/comparator/security/policy", "security": "https://github.com/sebastianbergmann/comparator/security/policy",
"source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2"
}, },
"funding": [ "funding": [
{ {
@ -4151,50 +4154,49 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v6.4.9", "version": "v7.1.3",
"version_normalized": "6.4.9.0", "version_normalized": "7.1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9" "reference": "cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9", "url": "https://api.github.com/repos/symfony/console/zipball/cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9",
"reference": "6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9", "reference": "cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3",
"symfony/string": "^5.4|^6.0|^7.0" "symfony/string": "^6.4|^7.0"
}, },
"conflict": { "conflict": {
"symfony/dependency-injection": "<5.4", "symfony/dependency-injection": "<6.4",
"symfony/dotenv": "<5.4", "symfony/dotenv": "<6.4",
"symfony/event-dispatcher": "<5.4", "symfony/event-dispatcher": "<6.4",
"symfony/lock": "<5.4", "symfony/lock": "<6.4",
"symfony/process": "<5.4" "symfony/process": "<6.4"
}, },
"provide": { "provide": {
"psr/log-implementation": "1.0|2.0|3.0" "psr/log-implementation": "1.0|2.0|3.0"
}, },
"require-dev": { "require-dev": {
"psr/log": "^1|^2|^3", "psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0|^7.0", "symfony/config": "^6.4|^7.0",
"symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^6.4|^7.0",
"symfony/event-dispatcher": "^5.4|^6.0|^7.0", "symfony/event-dispatcher": "^6.4|^7.0",
"symfony/http-foundation": "^6.4|^7.0", "symfony/http-foundation": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0",
"symfony/lock": "^5.4|^6.0|^7.0", "symfony/lock": "^6.4|^7.0",
"symfony/messenger": "^5.4|^6.0|^7.0", "symfony/messenger": "^6.4|^7.0",
"symfony/process": "^5.4|^6.0|^7.0", "symfony/process": "^6.4|^7.0",
"symfony/stopwatch": "^5.4|^6.0|^7.0", "symfony/stopwatch": "^6.4|^7.0",
"symfony/var-dumper": "^5.4|^6.0|^7.0" "symfony/var-dumper": "^6.4|^7.0"
}, },
"time": "2024-06-28T09:49:33+00:00", "time": "2024-07-26T12:41:01+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -4228,7 +4230,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v6.4.9" "source": "https://github.com/symfony/console/tree/v7.1.3"
}, },
"funding": [ "funding": [
{ {
@ -4318,25 +4320,25 @@
}, },
{ {
"name": "symfony/event-dispatcher", "name": "symfony/event-dispatcher",
"version": "v6.4.8", "version": "v7.1.1",
"version_normalized": "6.4.8.0", "version_normalized": "7.1.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/event-dispatcher.git", "url": "https://github.com/symfony/event-dispatcher.git",
"reference": "8d7507f02b06e06815e56bb39aa0128e3806208b" "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8d7507f02b06e06815e56bb39aa0128e3806208b", "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7",
"reference": "8d7507f02b06e06815e56bb39aa0128e3806208b", "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.2",
"symfony/event-dispatcher-contracts": "^2.5|^3" "symfony/event-dispatcher-contracts": "^2.5|^3"
}, },
"conflict": { "conflict": {
"symfony/dependency-injection": "<5.4", "symfony/dependency-injection": "<6.4",
"symfony/service-contracts": "<2.5" "symfony/service-contracts": "<2.5"
}, },
"provide": { "provide": {
@ -4345,15 +4347,15 @@
}, },
"require-dev": { "require-dev": {
"psr/log": "^1|^2|^3", "psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0|^7.0", "symfony/config": "^6.4|^7.0",
"symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^6.4|^7.0",
"symfony/error-handler": "^5.4|^6.0|^7.0", "symfony/error-handler": "^6.4|^7.0",
"symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/expression-language": "^6.4|^7.0",
"symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/http-foundation": "^6.4|^7.0",
"symfony/service-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3",
"symfony/stopwatch": "^5.4|^6.0|^7.0" "symfony/stopwatch": "^6.4|^7.0"
}, },
"time": "2024-05-31T14:49:08+00:00", "time": "2024-05-31T14:57:53+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -4381,7 +4383,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v6.4.8" "source": "https://github.com/symfony/event-dispatcher/tree/v7.1.1"
}, },
"funding": [ "funding": [
{ {
@ -4480,28 +4482,28 @@
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v6.4.9", "version": "v7.1.2",
"version_normalized": "6.4.9.0", "version_normalized": "7.1.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "b51ef8059159330b74a4d52f68e671033c0fe463" "reference": "92a91985250c251de9b947a14bb2c9390b1a562c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/b51ef8059159330b74a4d52f68e671033c0fe463", "url": "https://api.github.com/repos/symfony/filesystem/zipball/92a91985250c251de9b947a14bb2c9390b1a562c",
"reference": "b51ef8059159330b74a4d52f68e671033c0fe463", "reference": "92a91985250c251de9b947a14bb2c9390b1a562c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.2",
"symfony/polyfill-ctype": "~1.8", "symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8" "symfony/polyfill-mbstring": "~1.8"
}, },
"require-dev": { "require-dev": {
"symfony/process": "^5.4|^6.4|^7.0" "symfony/process": "^6.4|^7.0"
}, },
"time": "2024-06-28T09:49:33+00:00", "time": "2024-06-28T10:03:55+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -4529,7 +4531,7 @@
"description": "Provides basic utilities for the filesystem", "description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/filesystem/tree/v6.4.9" "source": "https://github.com/symfony/filesystem/tree/v7.1.2"
}, },
"funding": [ "funding": [
{ {
@ -4549,26 +4551,26 @@
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v6.4.8", "version": "v7.1.3",
"version_normalized": "6.4.8.0", "version_normalized": "7.1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
"reference": "3ef977a43883215d560a2cecb82ec8e62131471c" "reference": "717c6329886f32dc65e27461f80f2a465412fdca"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/3ef977a43883215d560a2cecb82ec8e62131471c", "url": "https://api.github.com/repos/symfony/finder/zipball/717c6329886f32dc65e27461f80f2a465412fdca",
"reference": "3ef977a43883215d560a2cecb82ec8e62131471c", "reference": "717c6329886f32dc65e27461f80f2a465412fdca",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1" "php": ">=8.2"
}, },
"require-dev": { "require-dev": {
"symfony/filesystem": "^6.0|^7.0" "symfony/filesystem": "^6.4|^7.0"
}, },
"time": "2024-05-31T14:49:08+00:00", "time": "2024-07-24T07:08:44+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -4596,7 +4598,7 @@
"description": "Finds files and directories via an intuitive fluent interface", "description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/finder/tree/v6.4.8" "source": "https://github.com/symfony/finder/tree/v7.1.3"
}, },
"funding": [ "funding": [
{ {
@ -4616,24 +4618,24 @@
}, },
{ {
"name": "symfony/options-resolver", "name": "symfony/options-resolver",
"version": "v6.4.8", "version": "v7.1.1",
"version_normalized": "6.4.8.0", "version_normalized": "7.1.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/options-resolver.git", "url": "https://github.com/symfony/options-resolver.git",
"reference": "22ab9e9101ab18de37839074f8a1197f55590c1b" "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/22ab9e9101ab18de37839074f8a1197f55590c1b", "url": "https://api.github.com/repos/symfony/options-resolver/zipball/47aa818121ed3950acd2b58d1d37d08a94f9bf55",
"reference": "22ab9e9101ab18de37839074f8a1197f55590c1b", "reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3" "symfony/deprecation-contracts": "^2.5|^3"
}, },
"time": "2024-05-31T14:49:08+00:00", "time": "2024-05-31T14:57:53+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -4666,7 +4668,7 @@
"options" "options"
], ],
"support": { "support": {
"source": "https://github.com/symfony/options-resolver/tree/v6.4.8" "source": "https://github.com/symfony/options-resolver/tree/v7.1.1"
}, },
"funding": [ "funding": [
{ {
@ -5178,23 +5180,23 @@
}, },
{ {
"name": "symfony/process", "name": "symfony/process",
"version": "v6.4.8", "version": "v7.1.3",
"version_normalized": "6.4.8.0", "version_normalized": "7.1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/process.git", "url": "https://github.com/symfony/process.git",
"reference": "8d92dd79149f29e89ee0f480254db595f6a6a2c5" "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/8d92dd79149f29e89ee0f480254db595f6a6a2c5", "url": "https://api.github.com/repos/symfony/process/zipball/7f2f542c668ad6c313dc4a5e9c3321f733197eca",
"reference": "8d92dd79149f29e89ee0f480254db595f6a6a2c5", "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1" "php": ">=8.2"
}, },
"time": "2024-05-31T14:49:08+00:00", "time": "2024-07-26T12:44:47+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -5222,7 +5224,7 @@
"description": "Executes commands in sub-processes", "description": "Executes commands in sub-processes",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/process/tree/v6.4.8" "source": "https://github.com/symfony/process/tree/v7.1.3"
}, },
"funding": [ "funding": [
{ {
@ -5328,24 +5330,24 @@
}, },
{ {
"name": "symfony/stopwatch", "name": "symfony/stopwatch",
"version": "v6.4.8", "version": "v7.1.1",
"version_normalized": "6.4.8.0", "version_normalized": "7.1.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/stopwatch.git", "url": "https://github.com/symfony/stopwatch.git",
"reference": "63e069eb616049632cde9674c46957819454b8aa" "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/63e069eb616049632cde9674c46957819454b8aa", "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d",
"reference": "63e069eb616049632cde9674c46957819454b8aa", "reference": "5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.2",
"symfony/service-contracts": "^2.5|^3" "symfony/service-contracts": "^2.5|^3"
}, },
"time": "2024-05-31T14:49:08+00:00", "time": "2024-05-31T14:57:53+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -5373,7 +5375,7 @@
"description": "Provides a way to profile code", "description": "Provides a way to profile code",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/stopwatch/tree/v6.4.8" "source": "https://github.com/symfony/stopwatch/tree/v7.1.1"
}, },
"funding": [ "funding": [
{ {
@ -5393,21 +5395,21 @@
}, },
{ {
"name": "symfony/string", "name": "symfony/string",
"version": "v6.4.9", "version": "v7.1.3",
"version_normalized": "6.4.9.0", "version_normalized": "7.1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/string.git", "url": "https://github.com/symfony/string.git",
"reference": "76792dbd99690a5ebef8050d9206c60c59e681d7" "reference": "ea272a882be7f20cad58d5d78c215001617b7f07"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/76792dbd99690a5ebef8050d9206c60c59e681d7", "url": "https://api.github.com/repos/symfony/string/zipball/ea272a882be7f20cad58d5d78c215001617b7f07",
"reference": "76792dbd99690a5ebef8050d9206c60c59e681d7", "reference": "ea272a882be7f20cad58d5d78c215001617b7f07",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.2",
"symfony/polyfill-ctype": "~1.8", "symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0",
@ -5417,13 +5419,14 @@
"symfony/translation-contracts": "<2.5" "symfony/translation-contracts": "<2.5"
}, },
"require-dev": { "require-dev": {
"symfony/error-handler": "^5.4|^6.0|^7.0", "symfony/emoji": "^7.1",
"symfony/http-client": "^5.4|^6.0|^7.0", "symfony/error-handler": "^6.4|^7.0",
"symfony/intl": "^6.2|^7.0", "symfony/http-client": "^6.4|^7.0",
"symfony/intl": "^6.4|^7.0",
"symfony/translation-contracts": "^2.5|^3.0", "symfony/translation-contracts": "^2.5|^3.0",
"symfony/var-exporter": "^5.4|^6.0|^7.0" "symfony/var-exporter": "^6.4|^7.0"
}, },
"time": "2024-06-28T09:25:38+00:00", "time": "2024-07-22T10:25:37+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -5462,7 +5465,7 @@
"utf8" "utf8"
], ],
"support": { "support": {
"source": "https://github.com/symfony/string/tree/v6.4.9" "source": "https://github.com/symfony/string/tree/v7.1.3"
}, },
"funding": [ "funding": [
{ {

View File

@ -3,7 +3,7 @@
'name' => 'codeigniter4/framework', 'name' => 'codeigniter4/framework',
'pretty_version' => 'dev-master', 'pretty_version' => 'dev-master',
'version' => 'dev-master', 'version' => 'dev-master',
'reference' => 'bbb89d27e6e055d07faa359bddec81032352d85e', 'reference' => 'c3e7e73142fef1433a98d1a53c3a9650bd01e896',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
@ -20,9 +20,9 @@
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'codeigniter/coding-standard' => array( 'codeigniter/coding-standard' => array(
'pretty_version' => 'v1.8.0', 'pretty_version' => 'v1.8.1',
'version' => '1.8.0.0', 'version' => '1.8.1.0',
'reference' => 'a523fd030be6360123a88655f39f0eb1650ee4bf', 'reference' => '2c16682b4a3754bc6694fef1056f686f32298ee3',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../codeigniter/coding-standard', 'install_path' => __DIR__ . '/../codeigniter/coding-standard',
'aliases' => array(), 'aliases' => array(),
@ -31,16 +31,16 @@
'codeigniter4/framework' => array( 'codeigniter4/framework' => array(
'pretty_version' => 'dev-master', 'pretty_version' => 'dev-master',
'version' => 'dev-master', 'version' => 'dev-master',
'reference' => 'bbb89d27e6e055d07faa359bddec81032352d85e', 'reference' => 'c3e7e73142fef1433a98d1a53c3a9650bd01e896',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'composer/pcre' => array( 'composer/pcre' => array(
'pretty_version' => '3.1.4', 'pretty_version' => '3.2.0',
'version' => '3.1.4.0', 'version' => '3.2.0.0',
'reference' => '04229f163664973f68f38f6f73d917799168ef24', 'reference' => 'ea4ab6f9580a4fd221e0418f2c357cdd39102a90',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/./pcre', 'install_path' => __DIR__ . '/./pcre',
'aliases' => array(), 'aliases' => array(),
@ -92,9 +92,9 @@
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'friendsofphp/php-cs-fixer' => array( 'friendsofphp/php-cs-fixer' => array(
'pretty_version' => 'v3.59.3', 'pretty_version' => 'v3.62.0',
'version' => '3.59.3.0', 'version' => '3.62.0.0',
'reference' => '30ba9ecc2b0e5205e578fe29973c15653d9bfd29', 'reference' => '627692f794d35c43483f34b01d94740df2a73507',
'type' => 'application', 'type' => 'application',
'install_path' => __DIR__ . '/../friendsofphp/php-cs-fixer', 'install_path' => __DIR__ . '/../friendsofphp/php-cs-fixer',
'aliases' => array(), 'aliases' => array(),
@ -191,9 +191,9 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'nexusphp/cs-config' => array( 'nexusphp/cs-config' => array(
'pretty_version' => 'v3.23.1', 'pretty_version' => 'v3.24.0',
'version' => '3.23.1.0', 'version' => '3.24.0.0',
'reference' => '323c8ca9c86a85d8cf9990e95079a7734bfbf4e6', 'reference' => 'fd0fdb458cbf42ba636a2ed218530b335421f33f',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../nexusphp/cs-config', 'install_path' => __DIR__ . '/../nexusphp/cs-config',
'aliases' => array(), 'aliases' => array(),
@ -236,9 +236,9 @@
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'phpoffice/phpspreadsheet' => array( 'phpoffice/phpspreadsheet' => array(
'pretty_version' => '2.2.0', 'pretty_version' => '2.2.2',
'version' => '2.2.0.0', 'version' => '2.2.2.0',
'reference' => 'b0993b7e4d9c860133365d115b176bc6e0f57022', 'reference' => 'ffbcee68069b073bff07a71eb321dcd9f2763513',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../phpoffice/phpspreadsheet', 'install_path' => __DIR__ . '/../phpoffice/phpspreadsheet',
'aliases' => array(), 'aliases' => array(),
@ -290,9 +290,9 @@
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'phpunit/phpunit' => array( 'phpunit/phpunit' => array(
'pretty_version' => '10.5.28', 'pretty_version' => '10.5.29',
'version' => '10.5.28.0', 'version' => '10.5.29.0',
'reference' => 'ff7fb85cdf88131b83e721fb2a327b664dbed275', 'reference' => '8e9e80872b4e8064401788ee8a32d40b4455318f',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../phpunit/phpunit', 'install_path' => __DIR__ . '/../phpunit/phpunit',
'aliases' => array(), 'aliases' => array(),
@ -428,9 +428,9 @@
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'react/socket' => array( 'react/socket' => array(
'pretty_version' => 'v1.15.0', 'pretty_version' => 'v1.16.0',
'version' => '1.15.0.0', 'version' => '1.16.0.0',
'reference' => '216d3aec0b87f04a40ca04f481e6af01bdd1d038', 'reference' => '23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../react/socket', 'install_path' => __DIR__ . '/../react/socket',
'aliases' => array(), 'aliases' => array(),
@ -473,9 +473,9 @@
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'sebastian/comparator' => array( 'sebastian/comparator' => array(
'pretty_version' => '5.0.1', 'pretty_version' => '5.0.2',
'version' => '5.0.1.0', 'version' => '5.0.2.0',
'reference' => '2db5010a484d53ebf536087a70b4a5423c102372', 'reference' => '2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../sebastian/comparator', 'install_path' => __DIR__ . '/../sebastian/comparator',
'aliases' => array(), 'aliases' => array(),
@ -590,9 +590,9 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'symfony/console' => array( 'symfony/console' => array(
'pretty_version' => 'v6.4.9', 'pretty_version' => 'v7.1.3',
'version' => '6.4.9.0', 'version' => '7.1.3.0',
'reference' => '6edb5363ec0c78ad4d48c5128ebf4d083d89d3a9', 'reference' => 'cb1dcb30ebc7005c29864ee78adb47b5fb7c3cd9',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/console', 'install_path' => __DIR__ . '/../symfony/console',
'aliases' => array(), 'aliases' => array(),
@ -608,9 +608,9 @@
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'symfony/event-dispatcher' => array( 'symfony/event-dispatcher' => array(
'pretty_version' => 'v6.4.8', 'pretty_version' => 'v7.1.1',
'version' => '6.4.8.0', 'version' => '7.1.1.0',
'reference' => '8d7507f02b06e06815e56bb39aa0128e3806208b', 'reference' => '9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/event-dispatcher', 'install_path' => __DIR__ . '/../symfony/event-dispatcher',
'aliases' => array(), 'aliases' => array(),
@ -632,27 +632,27 @@
), ),
), ),
'symfony/filesystem' => array( 'symfony/filesystem' => array(
'pretty_version' => 'v6.4.9', 'pretty_version' => 'v7.1.2',
'version' => '6.4.9.0', 'version' => '7.1.2.0',
'reference' => 'b51ef8059159330b74a4d52f68e671033c0fe463', 'reference' => '92a91985250c251de9b947a14bb2c9390b1a562c',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/filesystem', 'install_path' => __DIR__ . '/../symfony/filesystem',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'symfony/finder' => array( 'symfony/finder' => array(
'pretty_version' => 'v6.4.8', 'pretty_version' => 'v7.1.3',
'version' => '6.4.8.0', 'version' => '7.1.3.0',
'reference' => '3ef977a43883215d560a2cecb82ec8e62131471c', 'reference' => '717c6329886f32dc65e27461f80f2a465412fdca',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/finder', 'install_path' => __DIR__ . '/../symfony/finder',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'symfony/options-resolver' => array( 'symfony/options-resolver' => array(
'pretty_version' => 'v6.4.8', 'pretty_version' => 'v7.1.1',
'version' => '6.4.8.0', 'version' => '7.1.1.0',
'reference' => '22ab9e9101ab18de37839074f8a1197f55590c1b', 'reference' => '47aa818121ed3950acd2b58d1d37d08a94f9bf55',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/options-resolver', 'install_path' => __DIR__ . '/../symfony/options-resolver',
'aliases' => array(), 'aliases' => array(),
@ -713,9 +713,9 @@
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'symfony/process' => array( 'symfony/process' => array(
'pretty_version' => 'v6.4.8', 'pretty_version' => 'v7.1.3',
'version' => '6.4.8.0', 'version' => '7.1.3.0',
'reference' => '8d92dd79149f29e89ee0f480254db595f6a6a2c5', 'reference' => '7f2f542c668ad6c313dc4a5e9c3321f733197eca',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/process', 'install_path' => __DIR__ . '/../symfony/process',
'aliases' => array(), 'aliases' => array(),
@ -731,18 +731,18 @@
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'symfony/stopwatch' => array( 'symfony/stopwatch' => array(
'pretty_version' => 'v6.4.8', 'pretty_version' => 'v7.1.1',
'version' => '6.4.8.0', 'version' => '7.1.1.0',
'reference' => '63e069eb616049632cde9674c46957819454b8aa', 'reference' => '5b75bb1ac2ba1b9d05c47fc4b3046a625377d23d',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/stopwatch', 'install_path' => __DIR__ . '/../symfony/stopwatch',
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'symfony/string' => array( 'symfony/string' => array(
'pretty_version' => 'v6.4.9', 'pretty_version' => 'v7.1.3',
'version' => '6.4.9.0', 'version' => '7.1.3.0',
'reference' => '76792dbd99690a5ebef8050d9206c60c59e681d7', 'reference' => 'ea272a882be7f20cad58d5d78c215001617b7f07',
'type' => 'library', 'type' => 'library',
'install_path' => __DIR__ . '/../symfony/string', 'install_path' => __DIR__ . '/../symfony/string',
'aliases' => array(), 'aliases' => array(),

View File

@ -12,7 +12,8 @@ to understand the implications.
It thus makes it easier to work with static analysis tools like PHPStan or Psalm as it It thus makes it easier to work with static analysis tools like PHPStan or Psalm as it
simplifies and reduces the possible return values from all the `preg_*` functions which simplifies and reduces the possible return values from all the `preg_*` functions which
are quite packed with edge cases. are quite packed with edge cases. As of v2.2.0 / v3.2.0 the library also comes with a
[PHPStan extension](#phpstan-extension) for parsing regular expressions and giving you even better output types.
This library is a thin wrapper around `preg_*` functions with [some limitations](#restrictions--limitations). This library is a thin wrapper around `preg_*` functions with [some limitations](#restrictions--limitations).
If you are looking for a richer API to handle regular expressions have a look at If you are looking for a richer API to handle regular expressions have a look at
@ -175,6 +176,13 @@ preg_match('/(a)(b)*(c)(d)*/', 'ac', $matches, $flags);
| group 2 (any unmatched group preceding one that matched) is set to `''`. You cannot tell if it matched an empty string or did not match at all | group 2 is `null` when unmatched and a string if it matched, easy to check for | | group 2 (any unmatched group preceding one that matched) is set to `''`. You cannot tell if it matched an empty string or did not match at all | group 2 is `null` when unmatched and a string if it matched, easy to check for |
| group 4 (any optional group without a matching one following) is missing altogether. So you have to check with `isset()`, but really you want `isset($m[4]) && $m[4] !== ''` for safety unless you are very careful to check that a non-optional group follows it | group 4 is always set, and null in this case as there was no match, easy to check for with `$m[4] !== null` | | group 4 (any optional group without a matching one following) is missing altogether. So you have to check with `isset()`, but really you want `isset($m[4]) && $m[4] !== ''` for safety unless you are very careful to check that a non-optional group follows it | group 4 is always set, and null in this case as there was no match, easy to check for with `$m[4] !== null` |
PHPStan Extension
-----------------
To use the PHPStan extension if you do not use `phpstan/extension-installer` you can include `vendor/composer/pcre/extension.neon` in your PHPStan config.
The extension provides much better type information for $matches as well as regex validation where possible.
License License
------- -------

View File

@ -20,10 +20,13 @@
"php": "^7.4 || ^8.0" "php": "^7.4 || ^8.0"
}, },
"require-dev": { "require-dev": {
"symfony/phpunit-bridge": "^5", "phpunit/phpunit": "^8 || ^9",
"phpstan/phpstan": "^1.3", "phpstan/phpstan": "^1.11.8",
"phpstan/phpstan-strict-rules": "^1.1" "phpstan/phpstan-strict-rules": "^1.1"
}, },
"conflict": {
"phpstan/phpstan": "<1.11.8"
},
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Composer\\Pcre\\": "src" "Composer\\Pcre\\": "src"
@ -37,10 +40,15 @@
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "3.x-dev" "dev-main": "3.x-dev"
},
"phpstan": {
"includes": [
"extension.neon"
]
} }
}, },
"scripts": { "scripts": {
"test": "vendor/bin/simple-phpunit", "test": "@php vendor/bin/phpunit",
"phpstan": "phpstan analyse" "phpstan": "@php phpstan analyse"
} }
} }

View File

@ -43,6 +43,7 @@ class Regex
*/ */
public static function matchStrictGroups(string $pattern, string $subject, int $flags = 0, int $offset = 0): MatchStrictGroupsResult public static function matchStrictGroups(string $pattern, string $subject, int $flags = 0, int $offset = 0): MatchStrictGroupsResult
{ {
// @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
$count = Preg::matchStrictGroups($pattern, $subject, $matches, $flags, $offset); $count = Preg::matchStrictGroups($pattern, $subject, $matches, $flags, $offset);
return new MatchStrictGroupsResult($count, $matches); return new MatchStrictGroupsResult($count, $matches);
@ -87,6 +88,7 @@ class Regex
self::checkOffsetCapture($flags, 'matchAllWithOffsets'); self::checkOffsetCapture($flags, 'matchAllWithOffsets');
self::checkSetOrder($flags); self::checkSetOrder($flags);
// @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
$count = Preg::matchAllStrictGroups($pattern, $subject, $matches, $flags, $offset); $count = Preg::matchAllStrictGroups($pattern, $subject, $matches, $flags, $offset);
return new MatchAllStrictGroupsResult($count, $matches); return new MatchAllStrictGroupsResult($count, $matches);

View File

@ -8,6 +8,10 @@ if (!(PHP_VERSION_ID >= 80100)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.'; $issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
} }
if (PHP_INT_SIZE !== 8) {
$issues[] = 'Your Composer dependencies require a 64-bit build of PHP.';
}
if ($issues) { if ($issues) {
if (!headers_sent()) { if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error'); header('HTTP/1.1 500 Internal Server Error');

View File

@ -3,6 +3,56 @@ CHANGELOG for PHP CS Fixer
This file contains changelogs for stable releases only. This file contains changelogs for stable releases only.
Changelog for v3.62.0
---------------------
* feat: set new_with_parentheses for anonymous_class to false in PER-CS2.0 (#8140)
* chore: NewWithParenthesesFixer - create TODO to change the default configuration to match PER-CS2 (#8148)
Changelog for v3.61.1
---------------------
* fix: `NoSuperfluousPhpdocTagsFixer` - fix "Undefined array key 0" error (#8150)
Changelog for v3.61.0
---------------------
* feat: no_superfluous_phpdoc_tags - also cover ?type (#8125)
* feat: support PHPUnit v9.1 naming for some asserts (#7997)
* fix: Do not mangle non-whitespace token in `PhpdocIndentFixer` (#8147)
* DX: add more typehints for `class-string` (#8139)
* DX: refactor `ProjectCodeTest::provideDataProviderMethodCases` (#8138)
Changelog for v3.60.0
---------------------
* feat: Add sprintf in the list of compiler optimized functions (#8092)
* feat: `PhpUnitAttributesFixer` - add option to keep annotations (#8090)
* chore: cleanup tests that had `@requires PHP 7.4` ages ago (#8122)
* chore: cleanup `TokensAnalyzerTest` (#8123)
* chore: fix example issue reported by reportPossiblyNonexistentGeneralArrayOffset from PHPStan (#8089)
* chore: NoSuperfluousPhpdocTagsFixer - no need to call heavy toComparableNames method to add null type (#8132)
* chore: PHPStan 11 array rules (#8011)
* chore: PhpUnitSizeClassFixerTest - solve PHP 8.4 issues (#8105)
* chore: reduce PHPStan errors in PhpUnitAttributesFixer (#8091)
* chore: reuse test methods (#8119)
* CI: check autoload (#8121)
* CI: Update PHPStan to 1.11.8 (#8133)
* deps: upgrade dev-tools (#8102)
* DX: check for duplicated test data (#8131)
* DX: check for duplicated test methods (#8124)
* DX: check for duplicated test methods (as AutoReview test) (#8134)
* DX: do not exclude duplicates that are clearly mistakes (#8135)
* DX: Dump `offsetAccess.notFound` errors to baseline (#8107)
* fix: Better way of walking types in `TypeExpression` (#8076)
* fix: CI for PHP 8.4 (#8114)
* fix: update `TokensTest` to shrink PHPStan's baseline (#8112)
* fix: `no_useless_concat_operator` - do not break variable (2) (#7927)
* fix: `NullableTypeDeclarationFixer` - don't convert standalone `null` into nullable union type (#8098)
* fix: `NullableTypeDeclarationFixer` - don't convert standalone `NULL` into nullable union type (#8111)
* fix: `NullableTypeDeclarationFixer` - insert correct token (#8118)
* fix: `PhpUnitAttributesFixer` - handle multiple annotations of the same name (#8075)
Changelog for v3.59.3 Changelog for v3.59.3
--------------------- ---------------------

View File

@ -74,7 +74,10 @@
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {
"PhpCsFixer\\Tests\\": "tests/" "PhpCsFixer\\Tests\\": "tests/"
} },
"exclude-from-classmap": [
"tests/Fixtures/"
]
}, },
"bin": [ "bin": [
"php-cs-fixer" "php-cs-fixer"
@ -124,6 +127,7 @@
"self-check": [ "self-check": [
"./dev-tools/check_file_permissions.sh", "./dev-tools/check_file_permissions.sh",
"./dev-tools/check_trailing_spaces.sh", "./dev-tools/check_trailing_spaces.sh",
"@composer dump-autoload --dry-run --optimize --strict-psr",
"@normalize", "@normalize",
"@unused-deps", "@unused-deps",
"@require-checker", "@require-checker",

View File

@ -76,7 +76,7 @@ final class Cache implements CacheInterface
]); ]);
if (JSON_ERROR_NONE !== json_last_error() || false === $json) { if (JSON_ERROR_NONE !== json_last_error() || false === $json) {
throw new \UnexpectedValueException(sprintf( throw new \UnexpectedValueException(\sprintf(
'Cannot encode cache signature to JSON, error: "%s". If you have non-UTF8 chars in your signature, like in license for `header_comment`, consider enabling `ext-mbstring` or install `symfony/polyfill-mbstring`.', 'Cannot encode cache signature to JSON, error: "%s". If you have non-UTF8 chars in your signature, like in license for `header_comment`, consider enabling `ext-mbstring` or install `symfony/polyfill-mbstring`.',
json_last_error_msg() json_last_error_msg()
)); ));
@ -93,7 +93,7 @@ final class Cache implements CacheInterface
$data = json_decode($json, true); $data = json_decode($json, true);
if (null === $data && JSON_ERROR_NONE !== json_last_error()) { if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
throw new \InvalidArgumentException(sprintf( throw new \InvalidArgumentException(\sprintf(
'Value needs to be a valid JSON string, got "%s", error: "%s".', 'Value needs to be a valid JSON string, got "%s", error: "%s".',
$json, $json,
json_last_error_msg() json_last_error_msg()
@ -112,7 +112,7 @@ final class Cache implements CacheInterface
$missingKeys = array_diff_key(array_flip($requiredKeys), $data); $missingKeys = array_diff_key(array_flip($requiredKeys), $data);
if (\count($missingKeys) > 0) { if (\count($missingKeys) > 0) {
throw new \InvalidArgumentException(sprintf( throw new \InvalidArgumentException(\sprintf(
'JSON data is missing keys %s', 'JSON data is missing keys %s',
Utils::naturalLanguageJoin(array_keys($missingKeys)) Utils::naturalLanguageJoin(array_keys($missingKeys))
)); ));

View File

@ -140,7 +140,7 @@ final class FileHandler implements FileHandlerInterface
if ($this->fileInfo->isDir()) { if ($this->fileInfo->isDir()) {
throw new IOException( throw new IOException(
sprintf('Cannot write cache file "%s" as the location exists as directory.', $this->fileInfo->getRealPath()), \sprintf('Cannot write cache file "%s" as the location exists as directory.', $this->fileInfo->getRealPath()),
0, 0,
null, null,
$this->fileInfo->getPathname() $this->fileInfo->getPathname()
@ -149,7 +149,7 @@ final class FileHandler implements FileHandlerInterface
if ($this->fileInfo->isFile() && !$this->fileInfo->isWritable()) { if ($this->fileInfo->isFile() && !$this->fileInfo->isWritable()) {
throw new IOException( throw new IOException(
sprintf('Cannot write to file "%s" as it is not writable.', $this->fileInfo->getRealPath()), \sprintf('Cannot write to file "%s" as it is not writable.', $this->fileInfo->getRealPath()),
0, 0,
null, null,
$this->fileInfo->getPathname() $this->fileInfo->getPathname()
@ -171,7 +171,7 @@ final class FileHandler implements FileHandlerInterface
if (!@is_dir($dir)) { if (!@is_dir($dir)) {
throw new IOException( throw new IOException(
sprintf('Directory of cache file "%s" does not exists and couldn\'t be created.', $file), \sprintf('Directory of cache file "%s" does not exists and couldn\'t be created.', $file),
0, 0,
null, null,
$file $file

View File

@ -30,7 +30,7 @@ class InvalidFixerConfigurationException extends InvalidConfigurationException
public function __construct(string $fixerName, string $message, ?\Throwable $previous = null) public function __construct(string $fixerName, string $message, ?\Throwable $previous = null)
{ {
parent::__construct( parent::__construct(
sprintf('[%s] %s', $fixerName, $message), \sprintf('[%s] %s', $fixerName, $message),
FixCommandExitStatusCalculator::EXIT_STATUS_FLAG_HAS_INVALID_FIXER_CONFIG, FixCommandExitStatusCalculator::EXIT_STATUS_FLAG_HAS_INVALID_FIXER_CONFIG,
$previous $previous
); );

View File

@ -44,7 +44,7 @@ use Symfony\Component\Console\Output\OutputInterface;
final class Application extends BaseApplication final class Application extends BaseApplication
{ {
public const NAME = 'PHP CS Fixer'; public const NAME = 'PHP CS Fixer';
public const VERSION = '3.59.3'; public const VERSION = '3.62.0';
public const VERSION_CODENAME = '7th Gear'; public const VERSION_CODENAME = '7th Gear';
private ToolInfo $toolInfo; private ToolInfo $toolInfo;
@ -89,7 +89,7 @@ final class Application extends BaseApplication
if (\count($warnings) > 0) { if (\count($warnings) > 0) {
foreach ($warnings as $warning) { foreach ($warnings as $warning) {
$stdErr->writeln(sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', $warning)); $stdErr->writeln(\sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', $warning));
} }
$stdErr->writeln(''); $stdErr->writeln('');
} }
@ -107,7 +107,7 @@ final class Application extends BaseApplication
$stdErr->writeln(''); $stdErr->writeln('');
$stdErr->writeln($stdErr->isDecorated() ? '<bg=yellow;fg=black;>Detected deprecations in use:</>' : 'Detected deprecations in use:'); $stdErr->writeln($stdErr->isDecorated() ? '<bg=yellow;fg=black;>Detected deprecations in use:</>' : 'Detected deprecations in use:');
foreach ($triggeredDeprecations as $deprecation) { foreach ($triggeredDeprecations as $deprecation) {
$stdErr->writeln(sprintf('- %s', $deprecation)); $stdErr->writeln(\sprintf('- %s', $deprecation));
} }
} }
} }
@ -120,7 +120,7 @@ final class Application extends BaseApplication
*/ */
public static function getAbout(bool $decorated = false): string public static function getAbout(bool $decorated = false): string
{ {
$longVersion = sprintf('%s <info>%s</info>', self::NAME, self::VERSION); $longVersion = \sprintf('%s <info>%s</info>', self::NAME, self::VERSION);
$commit = '@git-commit@'; $commit = '@git-commit@';
$versionCommit = ''; $versionCommit = '';
@ -131,8 +131,8 @@ final class Application extends BaseApplication
$about = implode('', [ $about = implode('', [
$longVersion, $longVersion,
$versionCommit ? sprintf(' <info>(%s)</info>', $versionCommit) : '', // @phpstan-ignore-line to avoid `Ternary operator condition is always true|false.` $versionCommit ? \sprintf(' <info>(%s)</info>', $versionCommit) : '', // @phpstan-ignore-line to avoid `Ternary operator condition is always true|false.`
self::VERSION_CODENAME ? sprintf(' <info>%s</info>', self::VERSION_CODENAME) : '', // @phpstan-ignore-line to avoid `Ternary operator condition is always true|false.` self::VERSION_CODENAME ? \sprintf(' <info>%s</info>', self::VERSION_CODENAME) : '', // @phpstan-ignore-line to avoid `Ternary operator condition is always true|false.`
' by <comment>Fabien Potencier</comment>, <comment>Dariusz Ruminski</comment> and <comment>contributors</comment>.', ' by <comment>Fabien Potencier</comment>, <comment>Dariusz Ruminski</comment> and <comment>contributors</comment>.',
]); ]);

View File

@ -131,7 +131,7 @@ final class DescribeCommand extends Command
$this->describeList($output, $e->getType()); $this->describeList($output, $e->getType());
throw new \InvalidArgumentException(sprintf( throw new \InvalidArgumentException(\sprintf(
'%s "%s" not found.%s', '%s "%s" not found.%s',
ucfirst($e->getType()), ucfirst($e->getType()),
$name, $name,
@ -155,24 +155,24 @@ final class DescribeCommand extends Command
$definition = $fixer->getDefinition(); $definition = $fixer->getDefinition();
$output->writeln(sprintf('<fg=blue>Description of the <info>`%s`</info> rule.</>', $name)); $output->writeln(\sprintf('<fg=blue>Description of the <info>`%s`</info> rule.</>', $name));
$output->writeln(''); $output->writeln('');
if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
$output->writeln(sprintf('Fixer class: <comment>%s</comment>.', \get_class($fixer))); $output->writeln(\sprintf('Fixer class: <comment>%s</comment>.', \get_class($fixer)));
$output->writeln(''); $output->writeln('');
} }
if ($fixer instanceof DeprecatedFixerInterface) { if ($fixer instanceof DeprecatedFixerInterface) {
$successors = $fixer->getSuccessorsNames(); $successors = $fixer->getSuccessorsNames();
$message = [] === $successors $message = [] === $successors
? sprintf('it will be removed in version %d.0', Application::getMajorVersion() + 1) ? \sprintf('it will be removed in version %d.0', Application::getMajorVersion() + 1)
: sprintf('use %s instead', Utils::naturalLanguageJoinWithBackticks($successors)); : \sprintf('use %s instead', Utils::naturalLanguageJoinWithBackticks($successors));
$endMessage = '. '.ucfirst($message); $endMessage = '. '.ucfirst($message);
Utils::triggerDeprecation(new \RuntimeException(str_replace('`', '"', "Rule \"{$name}\" is deprecated{$endMessage}."))); Utils::triggerDeprecation(new \RuntimeException(str_replace('`', '"', "Rule \"{$name}\" is deprecated{$endMessage}.")));
$message = Preg::replace('/(`[^`]+`)/', '<info>$1</info>', $message); $message = Preg::replace('/(`[^`]+`)/', '<info>$1</info>', $message);
$output->writeln(sprintf('<error>DEPRECATED</error>: %s.', $message)); $output->writeln(\sprintf('<error>DEPRECATED</error>: %s.', $message));
$output->writeln(''); $output->writeln('');
} }
@ -216,7 +216,7 @@ final class DescribeCommand extends Command
$configurationDefinition = $fixer->getConfigurationDefinition(); $configurationDefinition = $fixer->getConfigurationDefinition();
$options = $configurationDefinition->getOptions(); $options = $configurationDefinition->getOptions();
$output->writeln(sprintf('Fixer is configurable using following option%s:', 1 === \count($options) ? '' : 's')); $output->writeln(\sprintf('Fixer is configurable using following option%s:', 1 === \count($options) ? '' : 's'));
foreach ($options as $option) { foreach ($options as $option) {
$line = '* <info>'.OutputFormatter::escape($option->getName()).'</info>'; $line = '* <info>'.OutputFormatter::escape($option->getName()).'</info>';
@ -239,7 +239,7 @@ final class DescribeCommand extends Command
$line .= ': '.lcfirst(Preg::replace('/\.$/', '', $description)).'; '; $line .= ': '.lcfirst(Preg::replace('/\.$/', '', $description)).'; ';
if ($option->hasDefault()) { if ($option->hasDefault()) {
$line .= sprintf( $line .= \sprintf(
'defaults to <comment>%s</comment>', 'defaults to <comment>%s</comment>',
Utils::toString($option->getDefault()) Utils::toString($option->getDefault())
); );
@ -290,7 +290,7 @@ final class DescribeCommand extends Command
$differ = new FullDiffer(); $differ = new FullDiffer();
$diffFormatter = new DiffConsoleFormatter( $diffFormatter = new DiffConsoleFormatter(
$output->isDecorated(), $output->isDecorated(),
sprintf( \sprintf(
'<comment> ---------- begin diff ----------</comment>%s%%s%s<comment> ----------- end diff -----------</comment>', '<comment> ---------- begin diff ----------</comment>%s%%s%s<comment> ----------- end diff -----------</comment>',
PHP_EOL, PHP_EOL,
PHP_EOL PHP_EOL
@ -317,12 +317,12 @@ final class DescribeCommand extends Command
if ($fixer instanceof ConfigurableFixerInterface) { if ($fixer instanceof ConfigurableFixerInterface) {
if (null === $configuration) { if (null === $configuration) {
$output->writeln(sprintf(' * Example #%d. Fixing with the <comment>default</comment> configuration.', $index + 1)); $output->writeln(\sprintf(' * Example #%d. Fixing with the <comment>default</comment> configuration.', $index + 1));
} else { } else {
$output->writeln(sprintf(' * Example #%d. Fixing with configuration: <comment>%s</comment>.', $index + 1, Utils::toString($codeSample->getConfiguration()))); $output->writeln(\sprintf(' * Example #%d. Fixing with configuration: <comment>%s</comment>.', $index + 1, Utils::toString($codeSample->getConfiguration())));
} }
} else { } else {
$output->writeln(sprintf(' * Example #%d.', $index + 1)); $output->writeln(\sprintf(' * Example #%d.', $index + 1));
} }
$output->writeln([$diffFormatter->format($diff, ' %s'), '']); $output->writeln([$diffFormatter->format($diff, ' %s'), '']);
@ -338,9 +338,9 @@ final class DescribeCommand extends Command
foreach ($ruleSetConfigs as $set => $config) { foreach ($ruleSetConfigs as $set => $config) {
if (null !== $config) { if (null !== $config) {
$output->writeln(sprintf('* <info>%s</info> with config: <comment>%s</comment>', $set, Utils::toString($config))); $output->writeln(\sprintf('* <info>%s</info> with config: <comment>%s</comment>', $set, Utils::toString($config)));
} else { } else {
$output->writeln(sprintf('* <info>%s</info> with <comment>default</comment> config', $set)); $output->writeln(\sprintf('* <info>%s</info> with <comment>default</comment> config', $set));
} }
} }
@ -357,7 +357,7 @@ final class DescribeCommand extends Command
$ruleSetDefinitions = RuleSets::getSetDefinitions(); $ruleSetDefinitions = RuleSets::getSetDefinitions();
$fixers = $this->getFixers(); $fixers = $this->getFixers();
$output->writeln(sprintf('<fg=blue>Description of the <info>`%s`</info> set.</>', $ruleSetDefinitions[$name]->getName())); $output->writeln(\sprintf('<fg=blue>Description of the <info>`%s`</info> set.</>', $ruleSetDefinitions[$name]->getName()));
$output->writeln(''); $output->writeln('');
$output->writeln($this->replaceRstLinks($ruleSetDefinitions[$name]->getDescription())); $output->writeln($this->replaceRstLinks($ruleSetDefinitions[$name]->getDescription()));
@ -373,7 +373,7 @@ final class DescribeCommand extends Command
foreach ($ruleSetDefinitions[$name]->getRules() as $rule => $config) { foreach ($ruleSetDefinitions[$name]->getRules() as $rule => $config) {
if (str_starts_with($rule, '@')) { if (str_starts_with($rule, '@')) {
$set = $ruleSetDefinitions[$rule]; $set = $ruleSetDefinitions[$rule];
$help .= sprintf( $help .= \sprintf(
" * <info>%s</info>%s\n | %s\n\n", " * <info>%s</info>%s\n | %s\n\n",
$rule, $rule,
$set->isRisky() ? ' <error>risky</error>' : '', $set->isRisky() ? ' <error>risky</error>' : '',
@ -387,12 +387,12 @@ final class DescribeCommand extends Command
$fixer = $fixers[$rule]; $fixer = $fixers[$rule];
$definition = $fixer->getDefinition(); $definition = $fixer->getDefinition();
$help .= sprintf( $help .= \sprintf(
" * <info>%s</info>%s\n | %s\n%s\n", " * <info>%s</info>%s\n | %s\n%s\n",
$rule, $rule,
$fixer->isRisky() ? ' <error>risky</error>' : '', $fixer->isRisky() ? ' <error>risky</error>' : '',
$definition->getSummary(), $definition->getSummary(),
true !== $config ? sprintf(" <comment>| Configuration: %s</comment>\n", Utils::toString($config)) : '' true !== $config ? \sprintf(" <comment>| Configuration: %s</comment>\n", Utils::toString($config)) : ''
); );
} }
@ -448,7 +448,7 @@ final class DescribeCommand extends Command
$items = $this->getSetNames(); $items = $this->getSetNames();
foreach ($items as $item) { foreach ($items as $item) {
$output->writeln(sprintf('* <info>%s</info>', $item)); $output->writeln(\sprintf('* <info>%s</info>', $item));
} }
} }
@ -457,7 +457,7 @@ final class DescribeCommand extends Command
$items = array_keys($this->getFixers()); $items = array_keys($this->getFixers());
foreach ($items as $item) { foreach ($items as $item) {
$output->writeln(sprintf('* <info>%s</info>', $item)); $output->writeln(\sprintf('* <info>%s</info>', $item));
} }
} }
} }

View File

@ -263,10 +263,10 @@ use Symfony\Component\Stopwatch\Stopwatch;
$stdErr->writeln(Application::getAboutWithRuntime(true)); $stdErr->writeln(Application::getAboutWithRuntime(true));
$isParallel = $resolver->getParallelConfig()->getMaxProcesses() > 1; $isParallel = $resolver->getParallelConfig()->getMaxProcesses() > 1;
$stdErr->writeln(sprintf( $stdErr->writeln(\sprintf(
'Running analysis on %d core%s.', 'Running analysis on %d core%s.',
$resolver->getParallelConfig()->getMaxProcesses(), $resolver->getParallelConfig()->getMaxProcesses(),
$isParallel ? sprintf( $isParallel ? \sprintf(
's with %d file%s per process', 's with %d file%s per process',
$resolver->getParallelConfig()->getFilesPerProcess(), $resolver->getParallelConfig()->getFilesPerProcess(),
$resolver->getParallelConfig()->getFilesPerProcess() > 1 ? 's' : '' $resolver->getParallelConfig()->getFilesPerProcess() > 1 ? 's' : ''
@ -275,26 +275,26 @@ use Symfony\Component\Stopwatch\Stopwatch;
/** @TODO v4 remove warnings related to parallel runner */ /** @TODO v4 remove warnings related to parallel runner */
$usageDocs = 'https://cs.symfony.com/doc/usage.html'; $usageDocs = 'https://cs.symfony.com/doc/usage.html';
$stdErr->writeln(sprintf( $stdErr->writeln(\sprintf(
$stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', $stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s',
$isParallel $isParallel
? 'Parallel runner is an experimental feature and may be unstable, use it at your own risk. Feedback highly appreciated!' ? 'Parallel runner is an experimental feature and may be unstable, use it at your own risk. Feedback highly appreciated!'
: sprintf( : \sprintf(
'You can enable parallel runner and speed up the analysis! Please see %s for more information.', 'You can enable parallel runner and speed up the analysis! Please see %s for more information.',
$stdErr->isDecorated() $stdErr->isDecorated()
? sprintf('<href=%s;bg=yellow;fg=red;bold>usage docs</>', OutputFormatter::escape($usageDocs)) ? \sprintf('<href=%s;bg=yellow;fg=red;bold>usage docs</>', OutputFormatter::escape($usageDocs))
: $usageDocs : $usageDocs
) )
)); ));
$configFile = $resolver->getConfigFile(); $configFile = $resolver->getConfigFile();
$stdErr->writeln(sprintf('Loaded config <comment>%s</comment>%s.', $resolver->getConfig()->getName(), null === $configFile ? '' : ' from "'.$configFile.'"')); $stdErr->writeln(\sprintf('Loaded config <comment>%s</comment>%s.', $resolver->getConfig()->getName(), null === $configFile ? '' : ' from "'.$configFile.'"'));
if ($resolver->getUsingCache()) { if ($resolver->getUsingCache()) {
$cacheFile = $resolver->getCacheFile(); $cacheFile = $resolver->getCacheFile();
if (is_file($cacheFile)) { if (is_file($cacheFile)) {
$stdErr->writeln(sprintf('Using cache file "%s".', $cacheFile)); $stdErr->writeln(\sprintf('Using cache file "%s".', $cacheFile));
} }
} }
} }
@ -303,7 +303,7 @@ use Symfony\Component\Stopwatch\Stopwatch;
if (null !== $stdErr && $resolver->configFinderIsOverridden()) { if (null !== $stdErr && $resolver->configFinderIsOverridden()) {
$stdErr->writeln( $stdErr->writeln(
sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', 'Paths from configuration file have been overridden by paths provided as command arguments.') \sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', 'Paths from configuration file have been overridden by paths provided as command arguments.')
); );
} }

View File

@ -80,7 +80,7 @@ final class ListSetsCommand extends Command
$formats = $factory->getFormats(); $formats = $factory->getFormats();
sort($formats); sort($formats);
throw new InvalidConfigurationException(sprintf('The format "%s" is not defined, supported are %s.', $format, Utils::naturalLanguageJoin($formats))); throw new InvalidConfigurationException(\sprintf('The format "%s" is not defined, supported are %s.', $format, Utils::naturalLanguageJoin($formats)));
} }
return $reporter; return $reporter;

View File

@ -102,7 +102,7 @@ final class SelfUpdateCommand extends Command
$latestVersion = $this->versionChecker->getLatestVersion(); $latestVersion = $this->versionChecker->getLatestVersion();
$latestVersionOfCurrentMajor = $this->versionChecker->getLatestVersionOfMajor($currentMajor); $latestVersionOfCurrentMajor = $this->versionChecker->getLatestVersionOfMajor($currentMajor);
} catch (\Exception $exception) { } catch (\Exception $exception) {
$output->writeln(sprintf( $output->writeln(\sprintf(
'<error>Unable to determine newest version: %s</error>', '<error>Unable to determine newest version: %s</error>',
$exception->getMessage() $exception->getMessage()
)); ));
@ -122,8 +122,8 @@ final class SelfUpdateCommand extends Command
0 !== $this->versionChecker->compareVersions($latestVersionOfCurrentMajor, $latestVersion) 0 !== $this->versionChecker->compareVersions($latestVersionOfCurrentMajor, $latestVersion)
&& true !== $input->getOption('force') && true !== $input->getOption('force')
) { ) {
$output->writeln(sprintf('<info>A new major version of PHP CS Fixer is available</info> (<comment>%s</comment>)', $latestVersion)); $output->writeln(\sprintf('<info>A new major version of PHP CS Fixer is available</info> (<comment>%s</comment>)', $latestVersion));
$output->writeln(sprintf('<info>Before upgrading please read</info> https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/%s/UPGRADE-v%s.md', $latestVersion, $currentMajor + 1)); $output->writeln(\sprintf('<info>Before upgrading please read</info> https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/%s/UPGRADE-v%s.md', $latestVersion, $currentMajor + 1));
$output->writeln('<info>If you are ready to upgrade run this command with</info> <comment>-f</comment>'); $output->writeln('<info>If you are ready to upgrade run this command with</info> <comment>-f</comment>');
$output->writeln('<info>Checking for new minor/patch version...</info>'); $output->writeln('<info>Checking for new minor/patch version...</info>');
@ -143,7 +143,7 @@ final class SelfUpdateCommand extends Command
} }
if (!is_writable($localFilename)) { if (!is_writable($localFilename)) {
$output->writeln(sprintf('<error>No permission to update</error> "%s" <error>file.</error>', $localFilename)); $output->writeln(\sprintf('<error>No permission to update</error> "%s" <error>file.</error>', $localFilename));
return 1; return 1;
} }
@ -152,7 +152,7 @@ final class SelfUpdateCommand extends Command
$remoteFilename = $this->toolInfo->getPharDownloadUri($remoteTag); $remoteFilename = $this->toolInfo->getPharDownloadUri($remoteTag);
if (false === @copy($remoteFilename, $tempFilename)) { if (false === @copy($remoteFilename, $tempFilename)) {
$output->writeln(sprintf('<error>Unable to download new version</error> %s <error>from the server.</error>', $remoteTag)); $output->writeln(\sprintf('<error>Unable to download new version</error> %s <error>from the server.</error>', $remoteTag));
return 1; return 1;
} }
@ -162,7 +162,7 @@ final class SelfUpdateCommand extends Command
$pharInvalidityReason = $this->pharChecker->checkFileValidity($tempFilename); $pharInvalidityReason = $this->pharChecker->checkFileValidity($tempFilename);
if (null !== $pharInvalidityReason) { if (null !== $pharInvalidityReason) {
unlink($tempFilename); unlink($tempFilename);
$output->writeln(sprintf('<error>The download of</error> %s <error>is corrupt (%s).</error>', $remoteTag, $pharInvalidityReason)); $output->writeln(\sprintf('<error>The download of</error> %s <error>is corrupt (%s).</error>', $remoteTag, $pharInvalidityReason));
$output->writeln('<error>Please re-run the "self-update" command to try again.</error>'); $output->writeln('<error>Please re-run the "self-update" command to try again.</error>');
return 1; return 1;
@ -170,7 +170,7 @@ final class SelfUpdateCommand extends Command
rename($tempFilename, $localFilename); rename($tempFilename, $localFilename);
$output->writeln(sprintf('<info>PHP CS Fixer updated</info> (<comment>%s</comment> -> <comment>%s</comment>)', $currentVersion, $remoteTag)); $output->writeln(\sprintf('<info>PHP CS Fixer updated</info> (<comment>%s</comment> -> <comment>%s</comment>)', $currentVersion, $remoteTag));
return 0; return 0;
} }

View File

@ -348,7 +348,7 @@ final class ConfigurationResolver
); );
if (\count($riskyFixers) > 0) { if (\count($riskyFixers) > 0) {
throw new InvalidConfigurationException(sprintf('The rules contain risky fixers (%s), but they are not allowed to run. Perhaps you forget to use --allow-risky=yes option?', Utils::naturalLanguageJoin($riskyFixers))); throw new InvalidConfigurationException(\sprintf('The rules contain risky fixers (%s), but they are not allowed to run. Perhaps you forget to use --allow-risky=yes option?', Utils::naturalLanguageJoin($riskyFixers)));
} }
} }
} }
@ -392,7 +392,7 @@ final class ConfigurationResolver
: $cwd.\DIRECTORY_SEPARATOR.$path; : $cwd.\DIRECTORY_SEPARATOR.$path;
if (!file_exists($absolutePath)) { if (!file_exists($absolutePath)) {
throw new InvalidConfigurationException(sprintf( throw new InvalidConfigurationException(\sprintf(
'The path "%s" is not readable.', 'The path "%s" is not readable.',
$path $path
)); ));
@ -422,7 +422,7 @@ final class ConfigurationResolver
? ProgressOutputType::NONE ? ProgressOutputType::NONE
: ProgressOutputType::BAR; : ProgressOutputType::BAR;
} elseif (!\in_array($progressType, ProgressOutputType::all(), true)) { } elseif (!\in_array($progressType, ProgressOutputType::all(), true)) {
throw new InvalidConfigurationException(sprintf( throw new InvalidConfigurationException(\sprintf(
'The progress type "%s" is not defined, supported are %s.', 'The progress type "%s" is not defined, supported are %s.',
$progressType, $progressType,
Utils::naturalLanguageJoin(ProgressOutputType::all()) Utils::naturalLanguageJoin(ProgressOutputType::all())
@ -452,7 +452,7 @@ final class ConfigurationResolver
$formats = $reporterFactory->getFormats(); $formats = $reporterFactory->getFormats();
sort($formats); sort($formats);
throw new InvalidConfigurationException(sprintf('The format "%s" is not defined, supported are %s.', $format, Utils::naturalLanguageJoin($formats))); throw new InvalidConfigurationException(\sprintf('The format "%s" is not defined, supported are %s.', $format, Utils::naturalLanguageJoin($formats)));
} }
} }
@ -551,7 +551,7 @@ final class ConfigurationResolver
if (null !== $configFile) { if (null !== $configFile) {
if (false === file_exists($configFile) || false === is_readable($configFile)) { if (false === file_exists($configFile) || false === is_readable($configFile)) {
throw new InvalidConfigurationException(sprintf('Cannot read config file "%s".', $configFile)); throw new InvalidConfigurationException(\sprintf('Cannot read config file "%s".', $configFile));
} }
return [$configFile]; return [$configFile];
@ -660,7 +660,7 @@ final class ConfigurationResolver
$rules = json_decode($rules, true); $rules = json_decode($rules, true);
if (JSON_ERROR_NONE !== json_last_error()) { if (JSON_ERROR_NONE !== json_last_error()) {
throw new InvalidConfigurationException(sprintf('Invalid JSON rules input: "%s".', json_last_error_msg())); throw new InvalidConfigurationException(\sprintf('Invalid JSON rules input: "%s".', json_last_error_msg()));
} }
return $rules; return $rules;
@ -701,7 +701,7 @@ final class ConfigurationResolver
foreach ($rules as $key => $value) { foreach ($rules as $key => $value) {
if (\is_int($key)) { if (\is_int($key)) {
throw new InvalidConfigurationException(sprintf('Missing value for "%s" rule/set.', $value)); throw new InvalidConfigurationException(\sprintf('Missing value for "%s" rule/set.', $value));
} }
$ruleSet[$key] = true; $ruleSet[$key] = true;
@ -777,7 +777,7 @@ final class ConfigurationResolver
foreach ($unknownFixers as $unknownFixer) { foreach ($unknownFixers as $unknownFixer) {
if (isset($renamedRules[$unknownFixer])) { // Check if present as old renamed rule if (isset($renamedRules[$unknownFixer])) { // Check if present as old renamed rule
$hasOldRule = true; $hasOldRule = true;
$message .= sprintf( $message .= \sprintf(
'"%s" is renamed (did you mean "%s"?%s), ', '"%s" is renamed (did you mean "%s"?%s), ',
$unknownFixer, $unknownFixer,
$renamedRules[$unknownFixer]['new_name'], $renamedRules[$unknownFixer]['new_name'],
@ -786,7 +786,7 @@ final class ConfigurationResolver
} else { // Go to normal matcher if it is not a renamed rule } else { // Go to normal matcher if it is not a renamed rule
$matcher = new WordMatcher($availableFixers); $matcher = new WordMatcher($availableFixers);
$alternative = $matcher->match($unknownFixer); $alternative = $matcher->match($unknownFixer);
$message .= sprintf( $message .= \sprintf(
'"%s"%s, ', '"%s"%s, ',
$unknownFixer, $unknownFixer,
null === $alternative ? '' : ' (did you mean "'.$alternative.'"?)' null === $alternative ? '' : ' (did you mean "'.$alternative.'"?)'
@ -808,8 +808,8 @@ final class ConfigurationResolver
if (isset($rules[$fixerName]) && $fixer instanceof DeprecatedFixerInterface) { if (isset($rules[$fixerName]) && $fixer instanceof DeprecatedFixerInterface) {
$successors = $fixer->getSuccessorsNames(); $successors = $fixer->getSuccessorsNames();
$messageEnd = [] === $successors $messageEnd = [] === $successors
? sprintf(' and will be removed in version %d.0.', Application::getMajorVersion() + 1) ? \sprintf(' and will be removed in version %d.0.', Application::getMajorVersion() + 1)
: sprintf('. Use %s instead.', str_replace('`', '"', Utils::naturalLanguageJoinWithBackticks($successors))); : \sprintf('. Use %s instead.', str_replace('`', '"', Utils::naturalLanguageJoinWithBackticks($successors)));
Utils::triggerDeprecation(new \RuntimeException("Rule \"{$fixerName}\" is deprecated{$messageEnd}")); Utils::triggerDeprecation(new \RuntimeException("Rule \"{$fixerName}\" is deprecated{$messageEnd}"));
} }
@ -836,7 +836,7 @@ final class ConfigurationResolver
$modes, $modes,
true true
)) { )) {
throw new InvalidConfigurationException(sprintf( throw new InvalidConfigurationException(\sprintf(
'The path-mode "%s" is not defined, supported are %s.', 'The path-mode "%s" is not defined, supported are %s.',
$this->options['path-mode'], $this->options['path-mode'],
Utils::naturalLanguageJoin($modes) Utils::naturalLanguageJoin($modes)
@ -926,7 +926,7 @@ final class ConfigurationResolver
private function setOption(string $name, $value): void private function setOption(string $name, $value): void
{ {
if (!\array_key_exists($name, $this->options)) { if (!\array_key_exists($name, $this->options)) {
throw new InvalidConfigurationException(sprintf('Unknown option name: "%s".', $name)); throw new InvalidConfigurationException(\sprintf('Unknown option name: "%s".', $name));
} }
$this->options[$name] = $value; $this->options[$name] = $value;
@ -937,7 +937,7 @@ final class ConfigurationResolver
$value = $this->options[$optionName]; $value = $this->options[$optionName];
if (!\is_string($value)) { if (!\is_string($value)) {
throw new InvalidConfigurationException(sprintf('Expected boolean or string value for option "%s".', $optionName)); throw new InvalidConfigurationException(\sprintf('Expected boolean or string value for option "%s".', $optionName));
} }
if ('yes' === $value) { if ('yes' === $value) {
@ -948,7 +948,7 @@ final class ConfigurationResolver
return false; return false;
} }
throw new InvalidConfigurationException(sprintf('Expected "yes" or "no" for option "%s", got "%s".', $optionName, $value)); throw new InvalidConfigurationException(\sprintf('Expected "yes" or "no" for option "%s", got "%s".', $optionName, $value));
} }
private static function separatedContextLessInclude(string $path): ConfigInterface private static function separatedContextLessInclude(string $path): ConfigInterface
@ -957,7 +957,7 @@ final class ConfigurationResolver
// verify that the config has an instance of Config // verify that the config has an instance of Config
if (!$config instanceof ConfigInterface) { if (!$config instanceof ConfigInterface) {
throw new InvalidConfigurationException(sprintf('The config file: "%s" does not return a "PhpCsFixer\ConfigInterface" instance. Got: "%s".', $path, \is_object($config) ? \get_class($config) : \gettype($config))); throw new InvalidConfigurationException(\sprintf('The config file: "%s" does not return a "PhpCsFixer\ConfigInterface" instance. Got: "%s".', $path, \is_object($config) ? \get_class($config) : \gettype($config)));
} }
return $config; return $config;

View File

@ -44,7 +44,7 @@ final class ErrorOutput
*/ */
public function listErrors(string $process, array $errors): void public function listErrors(string $process, array $errors): void
{ {
$this->output->writeln(['', sprintf( $this->output->writeln(['', \sprintf(
'Files that were not fixed due to errors reported during %s:', 'Files that were not fixed due to errors reported during %s:',
$process $process
)]); )]);
@ -52,13 +52,13 @@ final class ErrorOutput
$showDetails = $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE; $showDetails = $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
$showTrace = $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG; $showTrace = $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
foreach ($errors as $i => $error) { foreach ($errors as $i => $error) {
$this->output->writeln(sprintf('%4d) %s', $i + 1, $error->getFilePath())); $this->output->writeln(\sprintf('%4d) %s', $i + 1, $error->getFilePath()));
$e = $error->getSource(); $e = $error->getSource();
if (!$showDetails || null === $e) { if (!$showDetails || null === $e) {
continue; continue;
} }
$class = sprintf('[%s]', \get_class($e)); $class = \sprintf('[%s]', \get_class($e));
$message = $e->getMessage(); $message = $e->getMessage();
$code = $e->getCode(); $code = $e->getCode();
if (0 !== $code) { if (0 !== $code) {
@ -80,7 +80,7 @@ final class ErrorOutput
$line .= str_repeat(' ', $length - \strlen($line)); $line .= str_repeat(' ', $length - \strlen($line));
} }
$this->output->writeln(sprintf(' <error> %s </error>', $this->prepareOutput($line))); $this->output->writeln(\sprintf(' <error> %s </error>', $this->prepareOutput($line)));
} }
if ($showTrace && !$e instanceof LintingException) { // stack trace of lint exception is of no interest if ($showTrace && !$e instanceof LintingException) { // stack trace of lint exception is of no interest
@ -99,13 +99,13 @@ final class ErrorOutput
if (Error::TYPE_LINT === $error->getType() && 0 < \count($error->getAppliedFixers())) { if (Error::TYPE_LINT === $error->getType() && 0 < \count($error->getAppliedFixers())) {
$this->output->writeln(''); $this->output->writeln('');
$this->output->writeln(sprintf(' Applied fixers: <comment>%s</comment>', implode(', ', $error->getAppliedFixers()))); $this->output->writeln(\sprintf(' Applied fixers: <comment>%s</comment>', implode(', ', $error->getAppliedFixers())));
$diff = $error->getDiff(); $diff = $error->getDiff();
if (null !== $diff) { if (null !== $diff) {
$diffFormatter = new DiffConsoleFormatter( $diffFormatter = new DiffConsoleFormatter(
$this->isDecorated, $this->isDecorated,
sprintf( \sprintf(
'<comment> ---------- begin diff ----------</comment>%s%%s%s<comment> ----------- end diff -----------</comment>', '<comment> ---------- begin diff ----------</comment>%s%%s%s<comment> ----------- end diff -----------</comment>',
PHP_EOL, PHP_EOL,
PHP_EOL PHP_EOL
@ -132,18 +132,18 @@ final class ErrorOutput
private function outputTrace(array $trace): void private function outputTrace(array $trace): void
{ {
if (isset($trace['class'], $trace['type'], $trace['function'])) { if (isset($trace['class'], $trace['type'], $trace['function'])) {
$this->output->writeln(sprintf( $this->output->writeln(\sprintf(
' <comment>%s</comment>%s<comment>%s()</comment>', ' <comment>%s</comment>%s<comment>%s()</comment>',
$this->prepareOutput($trace['class']), $this->prepareOutput($trace['class']),
$this->prepareOutput($trace['type']), $this->prepareOutput($trace['type']),
$this->prepareOutput($trace['function']) $this->prepareOutput($trace['function'])
)); ));
} elseif (isset($trace['function'])) { } elseif (isset($trace['function'])) {
$this->output->writeln(sprintf(' <comment>%s()</comment>', $this->prepareOutput($trace['function']))); $this->output->writeln(\sprintf(' <comment>%s()</comment>', $this->prepareOutput($trace['function'])));
} }
if (isset($trace['file'])) { if (isset($trace['file'])) {
$this->output->writeln(sprintf(' in <info>%s</info> at line <info>%d</info>', $this->prepareOutput($trace['file']), $trace['line'])); $this->output->writeln(\sprintf(' in <info>%s</info> at line <info>%d</info>', $this->prepareOutput($trace['file']), $trace['line']));
} }
} }

View File

@ -82,7 +82,7 @@ final class DotsOutput implements ProgressOutputInterface
public function onFixerFileProcessed(FixerFileProcessedEvent $event): void public function onFixerFileProcessed(FixerFileProcessedEvent $event): void
{ {
$status = self::$eventStatusMap[$event->getStatus()]; $status = self::$eventStatusMap[$event->getStatus()];
$this->getOutput()->write($this->getOutput()->isDecorated() ? sprintf($status['format'], $status['symbol']) : $status['symbol']); $this->getOutput()->write($this->getOutput()->isDecorated() ? \sprintf($status['format'], $status['symbol']) : $status['symbol']);
++$this->processedFiles; ++$this->processedFiles;
@ -90,7 +90,7 @@ final class DotsOutput implements ProgressOutputInterface
$isLast = $this->processedFiles === $this->context->getFilesCount(); $isLast = $this->processedFiles === $this->context->getFilesCount();
if (0 === $symbolsOnCurrentLine || $isLast) { if (0 === $symbolsOnCurrentLine || $isLast) {
$this->getOutput()->write(sprintf( $this->getOutput()->write(\sprintf(
'%s %'.\strlen((string) $this->context->getFilesCount()).'d / %d (%3d%%)', '%s %'.\strlen((string) $this->context->getFilesCount()).'d / %d (%3d%%)',
$isLast && 0 !== $symbolsOnCurrentLine ? str_repeat(' ', $this->symbolsPerLine - $symbolsOnCurrentLine) : '', $isLast && 0 !== $symbolsOnCurrentLine ? str_repeat(' ', $this->symbolsPerLine - $symbolsOnCurrentLine) : '',
$this->processedFiles, $this->processedFiles,
@ -114,10 +114,10 @@ final class DotsOutput implements ProgressOutputInterface
continue; continue;
} }
$symbols[$symbol] = sprintf('%s-%s', $this->getOutput()->isDecorated() ? sprintf($status['format'], $symbol) : $symbol, $status['description']); $symbols[$symbol] = \sprintf('%s-%s', $this->getOutput()->isDecorated() ? \sprintf($status['format'], $symbol) : $symbol, $status['description']);
} }
$this->getOutput()->write(sprintf("\nLegend: %s\n", implode(', ', $symbols))); $this->getOutput()->write(\sprintf("\nLegend: %s\n", implode(', ', $symbols)));
} }
private function getOutput(): OutputInterface private function getOutput(): OutputInterface

View File

@ -38,7 +38,7 @@ final class ProgressOutputFactory
if (!$this->isBuiltInType($outputType)) { if (!$this->isBuiltInType($outputType)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
sprintf( \sprintf(
'Something went wrong, "%s" output type is not supported', 'Something went wrong, "%s" output type is not supported',
$outputType $outputType
) )

View File

@ -59,7 +59,7 @@ final class JunitReporter implements ReporterInterface
if ($reportSummary->getTime() > 0) { if ($reportSummary->getTime() > 0) {
$testsuite->setAttribute( $testsuite->setAttribute(
'time', 'time',
sprintf( \sprintf(
'%.3f', '%.3f',
$reportSummary->getTime() / 1_000 $reportSummary->getTime() / 1_000
) )

View File

@ -36,7 +36,7 @@ final class ReporterFactory
foreach (SymfonyFinder::create()->files()->name('*Reporter.php')->in(__DIR__) as $file) { foreach (SymfonyFinder::create()->files()->name('*Reporter.php')->in(__DIR__) as $file) {
$relativeNamespace = $file->getRelativePath(); $relativeNamespace = $file->getRelativePath();
$builtInReporters[] = sprintf( $builtInReporters[] = \sprintf(
'%s\%s%s', '%s\%s%s',
__NAMESPACE__, __NAMESPACE__,
'' !== $relativeNamespace ? $relativeNamespace.'\\' : '', '' !== $relativeNamespace ? $relativeNamespace.'\\' : '',
@ -60,7 +60,7 @@ final class ReporterFactory
$format = $reporter->getFormat(); $format = $reporter->getFormat();
if (isset($this->reporters[$format])) { if (isset($this->reporters[$format])) {
throw new \UnexpectedValueException(sprintf('Reporter for format "%s" is already registered.', $format)); throw new \UnexpectedValueException(\sprintf('Reporter for format "%s" is already registered.', $format));
} }
$this->reporters[$format] = $reporter; $this->reporters[$format] = $reporter;
@ -82,7 +82,7 @@ final class ReporterFactory
public function getReporter(string $format): ReporterInterface public function getReporter(string $format): ReporterInterface
{ {
if (!isset($this->reporters[$format])) { if (!isset($this->reporters[$format])) {
throw new \UnexpectedValueException(sprintf('Reporter for format "%s" is not registered.', $format)); throw new \UnexpectedValueException(\sprintf('Reporter for format "%s" is not registered.', $format));
} }
return $this->reporters[$format]; return $this->reporters[$format];

View File

@ -35,7 +35,7 @@ final class TextReporter implements ReporterInterface
$identifiedFiles = 0; $identifiedFiles = 0;
foreach ($reportSummary->getChanged() as $file => $fixResult) { foreach ($reportSummary->getChanged() as $file => $fixResult) {
++$identifiedFiles; ++$identifiedFiles;
$output .= sprintf('%4d) %s', $identifiedFiles, $file); $output .= \sprintf('%4d) %s', $identifiedFiles, $file);
if ($reportSummary->shouldAddAppliedFixers()) { if ($reportSummary->shouldAddAppliedFixers()) {
$output .= $this->getAppliedFixers( $output .= $this->getAppliedFixers(
@ -62,7 +62,7 @@ final class TextReporter implements ReporterInterface
*/ */
private function getAppliedFixers(bool $isDecoratedOutput, array $appliedFixers): string private function getAppliedFixers(bool $isDecoratedOutput, array $appliedFixers): string
{ {
return sprintf( return \sprintf(
$isDecoratedOutput ? ' (<comment>%s</comment>)' : ' (%s)', $isDecoratedOutput ? ' (<comment>%s</comment>)' : ' (%s)',
implode(', ', $appliedFixers) implode(', ', $appliedFixers)
); );
@ -74,7 +74,7 @@ final class TextReporter implements ReporterInterface
return ''; return '';
} }
$diffFormatter = new DiffConsoleFormatter($isDecoratedOutput, sprintf( $diffFormatter = new DiffConsoleFormatter($isDecoratedOutput, \sprintf(
'<comment> ---------- begin diff ----------</comment>%s%%s%s<comment> ----------- end diff -----------</comment>', '<comment> ---------- begin diff ----------</comment>%s%%s%s<comment> ----------- end diff -----------</comment>',
PHP_EOL, PHP_EOL,
PHP_EOL PHP_EOL
@ -89,7 +89,7 @@ final class TextReporter implements ReporterInterface
return ''; return '';
} }
return PHP_EOL.sprintf( return PHP_EOL.\sprintf(
'%s %d of %d %s in %.3f seconds, %.2f MB memory used'.PHP_EOL, '%s %d of %d %s in %.3f seconds, %.2f MB memory used'.PHP_EOL,
$isDryRun ? 'Found' : 'Fixed', $isDryRun ? 'Found' : 'Fixed',
$identifiedFiles, $identifiedFiles,

View File

@ -38,7 +38,7 @@ final class ReporterFactory
foreach (SymfonyFinder::create()->files()->name('*Reporter.php')->in(__DIR__) as $file) { foreach (SymfonyFinder::create()->files()->name('*Reporter.php')->in(__DIR__) as $file) {
$relativeNamespace = $file->getRelativePath(); $relativeNamespace = $file->getRelativePath();
$builtInReporters[] = sprintf( $builtInReporters[] = \sprintf(
'%s\%s%s', '%s\%s%s',
__NAMESPACE__, __NAMESPACE__,
'' !== $relativeNamespace ? $relativeNamespace.'\\' : '', '' !== $relativeNamespace ? $relativeNamespace.'\\' : '',
@ -59,7 +59,7 @@ final class ReporterFactory
$format = $reporter->getFormat(); $format = $reporter->getFormat();
if (isset($this->reporters[$format])) { if (isset($this->reporters[$format])) {
throw new \UnexpectedValueException(sprintf('Reporter for format "%s" is already registered.', $format)); throw new \UnexpectedValueException(\sprintf('Reporter for format "%s" is already registered.', $format));
} }
$this->reporters[$format] = $reporter; $this->reporters[$format] = $reporter;
@ -81,7 +81,7 @@ final class ReporterFactory
public function getReporter(string $format): ReporterInterface public function getReporter(string $format): ReporterInterface
{ {
if (!isset($this->reporters[$format])) { if (!isset($this->reporters[$format])) {
throw new \UnexpectedValueException(sprintf('Reporter for format "%s" is not registered.', $format)); throw new \UnexpectedValueException(\sprintf('Reporter for format "%s" is not registered.', $format));
} }
return $this->reporters[$format]; return $this->reporters[$format];

View File

@ -37,7 +37,7 @@ final class TextReporter implements ReporterInterface
$output = ''; $output = '';
foreach ($sets as $i => $set) { foreach ($sets as $i => $set) {
$output .= sprintf('%2d) %s', $i + 1, $set->getName()).PHP_EOL.' '.$set->getDescription().PHP_EOL; $output .= \sprintf('%2d) %s', $i + 1, $set->getName()).PHP_EOL.' '.$set->getDescription().PHP_EOL;
if ($set->isRisky()) { if ($set->isRisky()) {
$output .= ' Set contains risky rules.'.PHP_EOL; $output .= ' Set contains risky rules.'.PHP_EOL;

View File

@ -34,7 +34,7 @@ final class GithubClient implements GithubClientInterface
); );
if (false === $result) { if (false === $result) {
throw new \RuntimeException(sprintf('Failed to load tags at "%s".', $this->url)); throw new \RuntimeException(\sprintf('Failed to load tags at "%s".', $this->url));
} }
/** /**
@ -47,7 +47,7 @@ final class GithubClient implements GithubClientInterface
*/ */
$result = json_decode($result, true); $result = json_decode($result, true);
if (JSON_ERROR_NONE !== json_last_error()) { if (JSON_ERROR_NONE !== json_last_error()) {
throw new \RuntimeException(sprintf( throw new \RuntimeException(\sprintf(
'Failed to read response from "%s" as JSON: %s.', 'Failed to read response from "%s" as JSON: %s.',
$this->url, $this->url,
json_last_error_msg() json_last_error_msg()

View File

@ -50,7 +50,7 @@ final class WarningsDetector
if ($this->toolInfo->isInstalledByComposer()) { if ($this->toolInfo->isInstalledByComposer()) {
$details = $this->toolInfo->getComposerInstallationDetails(); $details = $this->toolInfo->getComposerInstallationDetails();
if (ToolInfo::COMPOSER_LEGACY_PACKAGE_NAME === $details['name']) { if (ToolInfo::COMPOSER_LEGACY_PACKAGE_NAME === $details['name']) {
$this->warnings[] = sprintf( $this->warnings[] = \sprintf(
'You are running PHP CS Fixer installed with old vendor `%s`. Please update to `%s`.', 'You are running PHP CS Fixer installed with old vendor `%s`. Please update to `%s`.',
ToolInfo::COMPOSER_LEGACY_PACKAGE_NAME, ToolInfo::COMPOSER_LEGACY_PACKAGE_NAME,
ToolInfo::COMPOSER_PACKAGE_NAME ToolInfo::COMPOSER_PACKAGE_NAME

View File

@ -42,7 +42,7 @@ final class DiffConsoleFormatter
? $this->template ? $this->template
: Preg::replace('/<[^<>]+>/', '', $this->template); : Preg::replace('/<[^<>]+>/', '', $this->template);
return sprintf( return \sprintf(
$template, $template,
implode( implode(
PHP_EOL, PHP_EOL,
@ -61,7 +61,7 @@ final class DiffConsoleFormatter
$colour = 'cyan'; $colour = 'cyan';
} }
return sprintf('<fg=%s>%s</fg=%s>', $colour, OutputFormatter::escape($matches[0]), $colour); return \sprintf('<fg=%s>%s</fg=%s>', $colour, OutputFormatter::escape($matches[0]), $colour);
}, },
$line, $line,
1, 1,
@ -73,7 +73,7 @@ final class DiffConsoleFormatter
} }
} }
return sprintf($lineTemplate, $line); return \sprintf($lineTemplate, $line);
}, },
Preg::split('#\R#u', $diff) Preg::split('#\R#u', $diff)
) )

View File

@ -176,7 +176,7 @@ final class Annotation
public function getVariableName(): ?string public function getVariableName(): ?string
{ {
$type = preg_quote($this->getTypesContent() ?? '', '/'); $type = preg_quote($this->getTypesContent() ?? '', '/');
$regex = sprintf( $regex = \sprintf(
'/@%s\s+(%s\s*)?(&\s*)?(\.{3}\s*)?(?<variable>\$%s)(?:.*|$)/', '/@%s\s+(%s\s*)?(&\s*)?(\.{3}\s*)?(?<variable>\$%s)(?:.*|$)/',
$this->tag->getName(), $this->tag->getName(),
$type, $type,

View File

@ -271,23 +271,37 @@ final class TypeExpression
*/ */
public function walkTypes(\Closure $callback): void public function walkTypes(\Closure $callback): void
{ {
foreach (array_reverse($this->innerTypeExpressions) as [ $innerValueOrig = $this->value;
'start_index' => $startIndex,
$startIndexOffset = 0;
foreach ($this->innerTypeExpressions as [
'start_index' => $startIndexOrig,
'expression' => $inner, 'expression' => $inner,
]) { ]) {
$initialValueLength = \strlen($inner->toString()); $innerLengthOrig = \strlen($inner->toString());
$inner->walkTypes($callback); $inner->walkTypes($callback);
$this->value = substr_replace( $this->value = substr_replace(
$this->value, $this->value,
$inner->toString(), $inner->toString(),
$startIndex, $startIndexOrig + $startIndexOffset,
$initialValueLength $innerLengthOrig
); );
$startIndexOffset += \strlen($inner->toString()) - $innerLengthOrig;
} }
$callback($this); $callback($this);
if ($this->value !== $innerValueOrig) {
$this->isUnionType = false;
$this->typesGlue = '|';
$this->innerTypeExpressions = [];
$this->parse();
}
} }
/** /**
@ -393,7 +407,9 @@ final class TypeExpression
$consumedValueLength = \strlen($matches[0][0]); $consumedValueLength = \strlen($matches[0][0]);
$index += $consumedValueLength; $index += $consumedValueLength;
if (\strlen($this->value) === $index) { if (\strlen($this->value) <= $index) {
\assert(\strlen($this->value) === $index);
return; return;
} }
} }

View File

@ -151,7 +151,7 @@ final class DocLexer
private function scan(string $input): void private function scan(string $input): void
{ {
if (!isset($this->regex)) { if (!isset($this->regex)) {
$this->regex = sprintf( $this->regex = \sprintf(
'/(%s)|%s/%s', '/(%s)|%s/%s',
implode(')|(', $this->getCatchablePatterns()), implode(')|(', $this->getCatchablePatterns()),
implode('|', $this->getNonCatchablePatterns()), implode('|', $this->getNonCatchablePatterns()),

View File

@ -256,7 +256,7 @@ final class Tokens extends \SplFixedArray
$type = \get_class($token); $type = \get_class($token);
} }
throw new \InvalidArgumentException(sprintf('Token must be an instance of PhpCsFixer\Doctrine\Annotation\Token, "%s" given.', $type)); throw new \InvalidArgumentException(\sprintf('Token must be an instance of PhpCsFixer\Doctrine\Annotation\Token, "%s" given.', $type));
} }
parent::offsetSet($index, $token); parent::offsetSet($index, $token);
@ -270,7 +270,7 @@ final class Tokens extends \SplFixedArray
public function offsetUnset($index): void public function offsetUnset($index): void
{ {
if (!isset($this[$index])) { if (!isset($this[$index])) {
throw new \OutOfBoundsException(sprintf('Index "%s" is invalid or does not exist.', $index)); throw new \OutOfBoundsException(\sprintf('Index "%s" is invalid or does not exist.', $index));
} }
$max = \count($this) - 1; $max = \count($this) - 1;

View File

@ -83,7 +83,7 @@ final class FixerDocumentGenerator
$alternatives = $fixer->getSuccessorsNames(); $alternatives = $fixer->getSuccessorsNames();
if (0 !== \count($alternatives)) { if (0 !== \count($alternatives)) {
$deprecationDescription .= RstUtils::toRst(sprintf( $deprecationDescription .= RstUtils::toRst(\sprintf(
"\n\nYou should use %s instead.", "\n\nYou should use %s instead.",
Utils::naturalLanguageJoinWithBackticks($alternatives) Utils::naturalLanguageJoinWithBackticks($alternatives)
), 0); ), 0);
@ -202,7 +202,7 @@ final class FixerDocumentGenerator
RST; RST;
foreach ($samples as $index => $sample) { foreach ($samples as $index => $sample) {
$title = sprintf('Example #%d', $index + 1); $title = \sprintf('Example #%d', $index + 1);
$titleLine = str_repeat('~', \strlen($title)); $titleLine = str_repeat('~', \strlen($title));
$doc .= "\n\n{$title}\n{$titleLine}"; $doc .= "\n\n{$title}\n{$titleLine}";
@ -210,7 +210,7 @@ final class FixerDocumentGenerator
if (null === $sample->getConfiguration()) { if (null === $sample->getConfiguration()) {
$doc .= "\n\n*Default* configuration."; $doc .= "\n\n*Default* configuration.";
} else { } else {
$doc .= sprintf( $doc .= \sprintf(
"\n\nWith configuration: ``%s``.", "\n\nWith configuration: ``%s``.",
Utils::toString($sample->getConfiguration()) Utils::toString($sample->getConfiguration())
); );
@ -380,7 +380,7 @@ final class FixerDocumentGenerator
the sample is not suitable for current version of PHP (%s). the sample is not suitable for current version of PHP (%s).
RST; RST;
return sprintf($error, PHP_VERSION); return \sprintf($error, PHP_VERSION);
} }
$old = $sample->getCode(); $old = $sample->getCode();

View File

@ -58,7 +58,7 @@ final class RuleSetDocumentationGenerator
if (0 !== \count($alternatives)) { if (0 !== \count($alternatives)) {
$deprecationDescription .= RstUtils::toRst( $deprecationDescription .= RstUtils::toRst(
sprintf( \sprintf(
"\n\nYou should use %s instead.", "\n\nYou should use %s instead.",
Utils::naturalLanguageJoinWithBackticks($alternatives) Utils::naturalLanguageJoinWithBackticks($alternatives)
), ),

View File

@ -61,7 +61,7 @@ final class FileReader
if (false === $content) { if (false === $content) {
$error = error_get_last(); $error = error_get_last();
throw new \RuntimeException(sprintf( throw new \RuntimeException(\sprintf(
'Failed to read content from "%s".%s', 'Failed to read content from "%s".%s',
$realPath, $realPath,
null !== $error ? ' '.$error['message'] : '' null !== $error ? ' '.$error['message'] : ''

View File

@ -19,6 +19,7 @@ use PhpCsFixer\DocBlock\DocBlock;
use PhpCsFixer\DocBlock\Line; use PhpCsFixer\DocBlock\Line;
use PhpCsFixer\Indicator\PhpUnitTestCaseIndicator; use PhpCsFixer\Indicator\PhpUnitTestCaseIndicator;
use PhpCsFixer\Tokenizer\Analyzer\AttributeAnalyzer; use PhpCsFixer\Tokenizer\Analyzer\AttributeAnalyzer;
use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer;
use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer; use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer;
use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer; use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer;
use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\CT;
@ -98,6 +99,52 @@ abstract class AbstractPhpUnitFixer extends AbstractFixer
return $tokens[$index]->isGivenKind(T_DOC_COMMENT); return $tokens[$index]->isGivenKind(T_DOC_COMMENT);
} }
/**
* @return iterable<array{
* index: int,
* loweredName: string,
* openBraceIndex: int,
* closeBraceIndex: int,
* }>
*/
protected function getPreviousAssertCall(Tokens $tokens, int $startIndex, int $endIndex): iterable
{
$functionsAnalyzer = new FunctionsAnalyzer();
for ($index = $endIndex; $index > $startIndex; --$index) {
$index = $tokens->getPrevTokenOfKind($index, [[T_STRING]]);
if (null === $index) {
return;
}
// test if "assert" something call
$loweredContent = strtolower($tokens[$index]->getContent());
if (!str_starts_with($loweredContent, 'assert')) {
continue;
}
// test candidate for simple calls like: ([\]+'some fixable call'(...))
$openBraceIndex = $tokens->getNextMeaningfulToken($index);
if (!$tokens[$openBraceIndex]->equals('(')) {
continue;
}
if (!$functionsAnalyzer->isTheSameClassCall($tokens, $index)) {
continue;
}
yield [
'index' => $index,
'loweredName' => $loweredContent,
'openBraceIndex' => $openBraceIndex,
'closeBraceIndex' => $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openBraceIndex),
];
}
}
private function createDocBlock(Tokens $tokens, int $docBlockIndex, string $annotation): void private function createDocBlock(Tokens $tokens, int $docBlockIndex, string $annotation): void
{ {
$lineEnd = $this->whitespacesConfig->getLineEnding(); $lineEnd = $this->whitespacesConfig->getLineEnding();

View File

@ -241,7 +241,7 @@ abstract class AbstractShortOperatorFixer extends AbstractFixer
return false; return false;
} }
throw new \InvalidArgumentException(sprintf('Not supported operator "%s".', $operatorToken->toJson())); throw new \InvalidArgumentException(\sprintf('Not supported operator "%s".', $operatorToken->toJson()));
} }
private function belongsToSwitchOrAlternativeSyntax(AlternativeSyntaxAnalyzer $alternativeSyntaxAnalyzer, Tokens $tokens, int $index): bool private function belongsToSwitchOrAlternativeSyntax(AlternativeSyntaxAnalyzer $alternativeSyntaxAnalyzer, Tokens $tokens, int $index): bool

View File

@ -247,6 +247,10 @@ mbereg_search_getregs();
break; break;
} }
if (!isset(self::SETS[$set])) {
throw new \LogicException(\sprintf('Set %s passed option validation, but not part of ::SETS.', $set));
}
$this->aliases = array_merge($this->aliases, self::SETS[$set]); $this->aliases = array_merge($this->aliases, self::SETS[$set]);
} }
} }
@ -317,7 +321,7 @@ mbereg_search_getregs();
$list = "List of sets to fix. Defined sets are:\n\n"; $list = "List of sets to fix. Defined sets are:\n\n";
foreach ($sets as $set => $description) { foreach ($sets as $set => $description) {
$list .= sprintf("* `%s` (%s);\n", $set, $description); $list .= \sprintf("* `%s` (%s);\n", $set, $description);
} }
$list = rtrim($list, ";\n").'.'; $list = rtrim($list, ";\n").'.';

View File

@ -131,7 +131,7 @@ final class RandomApiMigrationFixer extends AbstractFunctionReferenceFixer imple
->setAllowedValues([static function (array $value): bool { ->setAllowedValues([static function (array $value): bool {
foreach ($value as $functionName => $replacement) { foreach ($value as $functionName => $replacement) {
if (!\array_key_exists($functionName, self::$argumentCounts)) { if (!\array_key_exists($functionName, self::$argumentCounts)) {
throw new InvalidOptionsException(sprintf( throw new InvalidOptionsException(\sprintf(
'Function "%s" is not handled by the fixer.', 'Function "%s" is not handled by the fixer.',
$functionName $functionName
)); ));

View File

@ -149,6 +149,7 @@ settype($bar, "null");
if ('null' === $type) { if ('null' === $type) {
$this->fixSettypeNullCall($tokens, $functionNameIndex, $argumentToken); $this->fixSettypeNullCall($tokens, $functionNameIndex, $argumentToken);
} else { } else {
\assert(isset($map[$type]));
$this->fixSettypeCall($tokens, $functionNameIndex, $argumentToken, new Token($map[$type])); $this->fixSettypeCall($tokens, $functionNameIndex, $argumentToken, new Token($map[$type]));
} }
} }

View File

@ -15,9 +15,10 @@ declare(strict_types=1);
namespace PhpCsFixer\Fixer\ArrayNotation; namespace PhpCsFixer\Fixer\ArrayNotation;
use PhpCsFixer\AbstractFixer; use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\FixerDefinition\VersionSpecification;
use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample;
use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\Tokens;
@ -31,7 +32,10 @@ final class NormalizeIndexBraceFixer extends AbstractFixer
{ {
return new FixerDefinition( return new FixerDefinition(
'Array index should always be written by using square braces.', 'Array index should always be written by using square braces.',
[new CodeSample("<?php\necho \$sample{\$index};\n")] [new VersionSpecificCodeSample(
"<?php\necho \$sample{\$index};\n",
new VersionSpecification(null, 8_04_00 - 1)
)]
); );
} }

View File

@ -113,7 +113,7 @@ class InvalidName {}
} }
try { try {
$tokens = Tokens::fromCode(sprintf('<?php class %s {}', $file->getBasename('.php'))); $tokens = Tokens::fromCode(\sprintf('<?php class %s {}', $file->getBasename('.php')));
if ($tokens[3]->isKeyword() || $tokens[3]->isMagicConstant()) { if ($tokens[3]->isKeyword() || $tokens[3]->isMagicConstant()) {
// name cannot be a class name - detected by PHP 5.x // name cannot be a class name - detected by PHP 5.x
@ -134,7 +134,7 @@ class InvalidName {}
$realpath = realpath($this->configuration['dir']); $realpath = realpath($this->configuration['dir']);
if (false === $realpath) { if (false === $realpath) {
throw new \InvalidArgumentException(sprintf('Failed to resolve configured directory "%s".', $this->configuration['dir'])); throw new \InvalidArgumentException(\sprintf('Failed to resolve configured directory "%s".', $this->configuration['dir']));
} }
$this->configuration['dir'] = $realpath; $this->configuration['dir'] = $realpath;
@ -241,7 +241,7 @@ class InvalidName {}
$namespaceParts = array_reverse(explode('\\', $maxNamespace)); $namespaceParts = array_reverse(explode('\\', $maxNamespace));
foreach ($namespaceParts as $namespacePart) { foreach ($namespaceParts as $namespacePart) {
$nameCandidate = sprintf('%s_%s', $namespacePart, $name); $nameCandidate = \sprintf('%s_%s', $namespacePart, $name);
if (strtolower($nameCandidate) !== strtolower(substr($currentName, -\strlen($nameCandidate)))) { if (strtolower($nameCandidate) !== strtolower(substr($currentName, -\strlen($nameCandidate)))) {
break; break;

View File

@ -217,7 +217,7 @@ class Sample
if (!\in_array($type, $supportedTypes, true)) { if (!\in_array($type, $supportedTypes, true)) {
throw new InvalidOptionsException( throw new InvalidOptionsException(
sprintf( \sprintf(
'Unexpected element type, expected any of %s, got "%s".', 'Unexpected element type, expected any of %s, got "%s".',
Utils::naturalLanguageJoin($supportedTypes), Utils::naturalLanguageJoin($supportedTypes),
\gettype($type).'#'.$type \gettype($type).'#'.$type
@ -229,7 +229,7 @@ class Sample
if (!\in_array($spacing, $supportedSpacings, true)) { if (!\in_array($spacing, $supportedSpacings, true)) {
throw new InvalidOptionsException( throw new InvalidOptionsException(
sprintf( \sprintf(
'Unexpected spacing for element type "%s", expected any of %s, got "%s".', 'Unexpected spacing for element type "%s", expected any of %s, got "%s".',
$spacing, $spacing,
Utils::naturalLanguageJoin($supportedSpacings), Utils::naturalLanguageJoin($supportedSpacings),
@ -363,7 +363,7 @@ class Sample
return $tokens[$aboveElementDocCandidateIndex]->isGivenKind([T_DOC_COMMENT, CT::T_ATTRIBUTE_CLOSE]) ? 2 : 1; return $tokens[$aboveElementDocCandidateIndex]->isGivenKind([T_DOC_COMMENT, CT::T_ATTRIBUTE_CLOSE]) ? 2 : 1;
} }
throw new \RuntimeException(sprintf('Unknown spacing "%s".', $spacing)); throw new \RuntimeException(\sprintf('Unknown spacing "%s".', $spacing));
} }
/** /**

View File

@ -351,7 +351,7 @@ final class FinalInternalClassFixer extends AbstractFixer implements Configurabl
$oldConfigIsSet = $this->configuration[$oldConfigKey] !== $defaults; $oldConfigIsSet = $this->configuration[$oldConfigKey] !== $defaults;
if ($newConfigIsSet && $oldConfigIsSet) { if ($newConfigIsSet && $oldConfigIsSet) {
throw new InvalidFixerConfigurationException($this->getName(), sprintf('Configuration cannot contain deprecated option "%s" and new option "%s".', $oldConfigKey, $newConfigKey)); throw new InvalidFixerConfigurationException($this->getName(), \sprintf('Configuration cannot contain deprecated option "%s" and new option "%s".', $oldConfigKey, $newConfigKey));
} }
if ($oldConfigIsSet) { if ($oldConfigIsSet) {
@ -368,7 +368,7 @@ final class FinalInternalClassFixer extends AbstractFixer implements Configurabl
$intersect = array_intersect_assoc($this->configuration['include'], $this->configuration['exclude']); $intersect = array_intersect_assoc($this->configuration['include'], $this->configuration['exclude']);
if (\count($intersect) > 0) { if (\count($intersect) > 0) {
throw new InvalidFixerConfigurationException($this->getName(), sprintf('Annotation cannot be used in both "include" and "exclude" list, got duplicates: %s.', Utils::naturalLanguageJoin(array_keys($intersect)))); throw new InvalidFixerConfigurationException($this->getName(), \sprintf('Annotation cannot be used in both "include" and "exclude" list, got duplicates: %s.', Utils::naturalLanguageJoin(array_keys($intersect))));
} }
} }
} }

View File

@ -99,7 +99,7 @@ final class SingleLineCommentSpacingFixer extends AbstractFixer
// fix space between comment open and leading text // fix space between comment open and leading text
private function fixCommentLeadingSpace(string $content, string $prefix): string private function fixCommentLeadingSpace(string $content, string $prefix): string
{ {
if (Preg::match(sprintf('@^%s\h+.*$@', preg_quote($prefix, '@')), $content)) { if (Preg::match(\sprintf('@^%s\h+.*$@', preg_quote($prefix, '@')), $content)) {
return $content; return $content;
} }

View File

@ -209,7 +209,7 @@ namespace {
$constantChecker = static function (array $value): bool { $constantChecker = static function (array $value): bool {
foreach ($value as $constantName) { foreach ($value as $constantName) {
if (trim($constantName) !== $constantName) { if (trim($constantName) !== $constantName) {
throw new InvalidOptionsException(sprintf( throw new InvalidOptionsException(\sprintf(
'Each element must be a non-empty, trimmed string, got "%s" instead.', 'Each element must be a non-empty, trimmed string, got "%s" instead.',
get_debug_type($constantName) get_debug_type($constantName)
)); ));

View File

@ -109,7 +109,7 @@ final class TrailingCommaInMultilineFixer extends AbstractFixer implements Confi
->setAllowedTypes(['bool']) ->setAllowedTypes(['bool'])
->setDefault(false) ->setDefault(false)
->getOption(), ->getOption(),
(new FixerOptionBuilder('elements', sprintf('Where to fix multiline trailing comma (PHP >= 8.0 for `%s` and `%s`).', self::ELEMENTS_PARAMETERS, self::MATCH_EXPRESSIONS))) // @TODO: remove text when PHP 8.0+ is required (new FixerOptionBuilder('elements', \sprintf('Where to fix multiline trailing comma (PHP >= 8.0 for `%s` and `%s`).', self::ELEMENTS_PARAMETERS, self::MATCH_EXPRESSIONS))) // @TODO: remove text when PHP 8.0+ is required
->setAllowedTypes(['string[]']) ->setAllowedTypes(['string[]'])
->setAllowedValues([new AllowedValueSubset([self::ELEMENTS_ARRAYS, self::ELEMENTS_ARGUMENTS, self::ELEMENTS_PARAMETERS, self::MATCH_EXPRESSIONS])]) ->setAllowedValues([new AllowedValueSubset([self::ELEMENTS_ARRAYS, self::ELEMENTS_ARGUMENTS, self::ELEMENTS_PARAMETERS, self::MATCH_EXPRESSIONS])])
->setDefault([self::ELEMENTS_ARRAYS]) ->setDefault([self::ELEMENTS_ARRAYS])
@ -117,7 +117,7 @@ final class TrailingCommaInMultilineFixer extends AbstractFixer implements Confi
if (\PHP_VERSION_ID < 8_00_00) { // @TODO: drop condition when PHP 8.0+ is required if (\PHP_VERSION_ID < 8_00_00) { // @TODO: drop condition when PHP 8.0+ is required
foreach ([self::ELEMENTS_PARAMETERS, self::MATCH_EXPRESSIONS] as $option) { foreach ([self::ELEMENTS_PARAMETERS, self::MATCH_EXPRESSIONS] as $option) {
if (\in_array($option, $value, true)) { if (\in_array($option, $value, true)) {
throw new InvalidOptionsForEnvException(sprintf('"%s" option can only be enabled with PHP 8.0+.', $option)); throw new InvalidOptionsForEnvException(\sprintf('"%s" option can only be enabled with PHP 8.0+.', $option));
} }
} }
} }

View File

@ -354,7 +354,7 @@ return $foo === count($bar);
private function fixTokensComparePart(Tokens $tokens, int $start, int $end): Tokens private function fixTokensComparePart(Tokens $tokens, int $start, int $end): Tokens
{ {
$newTokens = $tokens->generatePartialCode($start, $end); $newTokens = $tokens->generatePartialCode($start, $end);
$newTokens = $this->fixTokens(Tokens::fromCode(sprintf('<?php %s;', $newTokens))); $newTokens = $this->fixTokens(Tokens::fromCode(\sprintf('<?php %s;', $newTokens)));
$newTokens->clearAt(\count($newTokens) - 1); $newTokens->clearAt(\count($newTokens) - 1);
$newTokens->clearAt(0); $newTokens->clearAt(0);
$newTokens->clearEmptyTokens(); $newTokens->clearEmptyTokens();

View File

@ -223,7 +223,7 @@ $c = get_class($d);
->setAllowedValues([static function (array $value): bool { ->setAllowedValues([static function (array $value): bool {
foreach ($value as $functionName) { foreach ($value as $functionName) {
if ('' === trim($functionName) || trim($functionName) !== $functionName) { if ('' === trim($functionName) || trim($functionName) !== $functionName) {
throw new InvalidOptionsException(sprintf( throw new InvalidOptionsException(\sprintf(
'Each element must be a non-empty, trimmed string, got "%s" instead.', 'Each element must be a non-empty, trimmed string, got "%s" instead.',
get_debug_type($functionName) get_debug_type($functionName)
)); ));
@ -239,7 +239,7 @@ $c = get_class($d);
->setAllowedValues([static function (array $value): bool { ->setAllowedValues([static function (array $value): bool {
foreach ($value as $functionName) { foreach ($value as $functionName) {
if ('' === trim($functionName) || trim($functionName) !== $functionName) { if ('' === trim($functionName) || trim($functionName) !== $functionName) {
throw new InvalidOptionsException(sprintf( throw new InvalidOptionsException(\sprintf(
'Each element must be a non-empty, trimmed string, got "%s" instead.', 'Each element must be a non-empty, trimmed string, got "%s" instead.',
get_debug_type($functionName) get_debug_type($functionName)
)); ));
@ -252,7 +252,7 @@ $c = get_class($d);
]; ];
if (str_starts_with($functionName, '@') && !\in_array($functionName, $sets, true)) { if (str_starts_with($functionName, '@') && !\in_array($functionName, $sets, true)) {
throw new InvalidOptionsException(sprintf('Unknown set "%s", known sets are %s.', $functionName, Utils::naturalLanguageJoin($sets))); throw new InvalidOptionsException(\sprintf('Unknown set "%s", known sets are %s.', $functionName, Utils::naturalLanguageJoin($sets)));
} }
} }
@ -378,6 +378,7 @@ $c = get_class($d);
'is_string', 'is_string',
'ord', 'ord',
'sizeof', 'sizeof',
'sprintf',
'strlen', 'strlen',
'strval', 'strval',
// @see https://github.com/php/php-src/blob/php-7.2.6/ext/opcache/Optimizer/pass1_5.c // @see https://github.com/php/php-src/blob/php-7.2.6/ext/opcache/Optimizer/pass1_5.c

View File

@ -187,7 +187,7 @@ function bar($foo) {}
continue; continue;
} }
if (!$this->isValidSyntax(sprintf(self::TYPE_CHECK_TEMPLATE, $paramType))) { if (!$this->isValidSyntax(\sprintf(self::TYPE_CHECK_TEMPLATE, $paramType))) {
continue; continue;
} }
@ -201,7 +201,7 @@ function bar($foo) {}
protected function createTokensFromRawType(string $type): Tokens protected function createTokensFromRawType(string $type): Tokens
{ {
$typeTokens = Tokens::fromCode(sprintf(self::TYPE_CHECK_TEMPLATE, $type)); $typeTokens = Tokens::fromCode(\sprintf(self::TYPE_CHECK_TEMPLATE, $type));
$typeTokens->clearRange(0, 4); $typeTokens->clearRange(0, 4);
$typeTokens->clearRange(\count($typeTokens) - 6, \count($typeTokens) - 1); $typeTokens->clearRange(\count($typeTokens) - 6, \count($typeTokens) - 1);
$typeTokens->clearEmptyTokens(); $typeTokens->clearEmptyTokens();

View File

@ -125,7 +125,7 @@ class Foo {
protected function createTokensFromRawType(string $type): Tokens protected function createTokensFromRawType(string $type): Tokens
{ {
$typeTokens = Tokens::fromCode(sprintf(self::TYPE_CHECK_TEMPLATE, $type)); $typeTokens = Tokens::fromCode(\sprintf(self::TYPE_CHECK_TEMPLATE, $type));
$typeTokens->clearRange(0, 8); $typeTokens->clearRange(0, 8);
$typeTokens->clearRange(\count($typeTokens) - 5, \count($typeTokens) - 1); $typeTokens->clearRange(\count($typeTokens) - 5, \count($typeTokens) - 1);
$typeTokens->clearEmptyTokens(); $typeTokens->clearEmptyTokens();
@ -176,7 +176,7 @@ class Foo {
continue; continue;
} }
if (!$this->isValidSyntax(sprintf(self::TYPE_CHECK_TEMPLATE, $propertyType))) { if (!$this->isValidSyntax(\sprintf(self::TYPE_CHECK_TEMPLATE, $propertyType))) {
continue; continue;
} }

View File

@ -205,7 +205,7 @@ final class Foo {
continue; continue;
} }
if (!$this->isValidSyntax(sprintf(self::TYPE_CHECK_TEMPLATE, $returnType))) { if (!$this->isValidSyntax(\sprintf(self::TYPE_CHECK_TEMPLATE, $returnType))) {
continue; continue;
} }
@ -224,7 +224,7 @@ final class Foo {
protected function createTokensFromRawType(string $type): Tokens protected function createTokensFromRawType(string $type): Tokens
{ {
$typeTokens = Tokens::fromCode(sprintf(self::TYPE_CHECK_TEMPLATE, $type)); $typeTokens = Tokens::fromCode(\sprintf(self::TYPE_CHECK_TEMPLATE, $type));
$typeTokens->clearRange(0, 7); $typeTokens->clearRange(0, 7);
$typeTokens->clearRange(\count($typeTokens) - 3, \count($typeTokens) - 1); $typeTokens->clearRange(\count($typeTokens) - 3, \count($typeTokens) - 1);
$typeTokens->clearEmptyTokens(); $typeTokens->clearEmptyTokens();

View File

@ -98,7 +98,7 @@ final class GroupImportFixer extends AbstractFixer implements ConfigurableFixerI
foreach ($types as $type) { foreach ($types as $type) {
if (!\in_array($type, $allowedTypes, true)) { if (!\in_array($type, $allowedTypes, true)) {
throw new InvalidOptionsException( throw new InvalidOptionsException(
sprintf( \sprintf(
'Invalid group type: %s, allowed types: %s.', 'Invalid group type: %s, allowed types: %s.',
$type, $type,
Utils::naturalLanguageJoin($allowedTypes) Utils::naturalLanguageJoin($allowedTypes)

View File

@ -271,7 +271,7 @@ use Bar;
if (null !== $value) { if (null !== $value) {
$missing = array_diff($supportedSortTypes, $value); $missing = array_diff($supportedSortTypes, $value);
if (\count($missing) > 0) { if (\count($missing) > 0) {
throw new InvalidOptionsException(sprintf( throw new InvalidOptionsException(\sprintf(
'Missing sort %s %s.', 'Missing sort %s %s.',
1 === \count($missing) ? 'type' : 'types', 1 === \count($missing) ? 'type' : 'types',
Utils::naturalLanguageJoin($missing) Utils::naturalLanguageJoin($missing)
@ -280,7 +280,7 @@ use Bar;
$unknown = array_diff($value, $supportedSortTypes); $unknown = array_diff($value, $supportedSortTypes);
if (\count($unknown) > 0) { if (\count($unknown) > 0) {
throw new InvalidOptionsException(sprintf( throw new InvalidOptionsException(\sprintf(
'Unknown sort %s %s.', 'Unknown sort %s %s.',
1 === \count($unknown) ? 'type' : 'types', 1 === \count($unknown) ? 'type' : 'types',
Utils::naturalLanguageJoin($unknown) Utils::naturalLanguageJoin($unknown)
@ -562,7 +562,7 @@ use Bar;
// Now insert the new tokens, starting from the end // Now insert the new tokens, starting from the end
foreach (array_reverse($usesOrder, true) as $index => $use) { foreach (array_reverse($usesOrder, true) as $index => $use) {
$code = sprintf( $code = \sprintf(
'<?php use %s%s;', '<?php use %s%s;',
self::IMPORT_TYPE_CLASS === $use['importType'] ? '' : ' '.$use['importType'].' ', self::IMPORT_TYPE_CLASS === $use['importType'] ? '' : ' '.$use['importType'].' ',
$use['namespace'] $use['namespace']

View File

@ -183,12 +183,12 @@ class ValueObject
private function isTypeNormalizable(TypeAnalysis $typeAnalysis): bool private function isTypeNormalizable(TypeAnalysis $typeAnalysis): bool
{ {
if (!$typeAnalysis->isNullable()) { $type = $typeAnalysis->getName();
if ('null' === strtolower($type) || !$typeAnalysis->isNullable()) {
return false; return false;
} }
$type = $typeAnalysis->getName();
if (str_contains($type, '&')) { if (str_contains($type, '&')) {
return false; // skip DNF types return false; // skip DNF types
} }
@ -307,18 +307,18 @@ class ValueObject
private function createTypeDeclarationTokens(array $types, bool $isQuestionMarkSyntax): array private function createTypeDeclarationTokens(array $types, bool $isQuestionMarkSyntax): array
{ {
static $specialTypes = [ static $specialTypes = [
'?' => [CT::T_NULLABLE_TYPE, '?'], '?' => CT::T_NULLABLE_TYPE,
'array' => [CT::T_ARRAY_TYPEHINT, 'array'], 'array' => CT::T_ARRAY_TYPEHINT,
'callable' => [T_CALLABLE, 'callable'], 'callable' => T_CALLABLE,
'static' => [T_STATIC, 'static'], 'static' => T_STATIC,
]; ];
$count = \count($types); $count = \count($types);
$newTokens = []; $newTokens = [];
foreach ($types as $index => $type) { foreach ($types as $index => $type) {
if (isset($specialTypes[$type])) { if (isset($specialTypes[strtolower($type)])) {
$newTokens[] = new Token($specialTypes[$type]); $newTokens[] = new Token([$specialTypes[strtolower($type)], $type]);
} else { } else {
foreach (explode('\\', $type) as $nsIndex => $value) { foreach (explode('\\', $type) as $nsIndex => $value) {
if (0 === $nsIndex && '' === $value) { if (0 === $nsIndex && '' === $value) {

View File

@ -376,7 +376,7 @@ $array = [
foreach ($option as $operator => $value) { foreach ($option as $operator => $value) {
if (!\in_array($operator, self::SUPPORTED_OPERATORS, true)) { if (!\in_array($operator, self::SUPPORTED_OPERATORS, true)) {
throw new InvalidOptionsException( throw new InvalidOptionsException(
sprintf( \sprintf(
'Unexpected "operators" key, expected any of %s, got "%s".', 'Unexpected "operators" key, expected any of %s, got "%s".',
Utils::naturalLanguageJoin(self::SUPPORTED_OPERATORS), Utils::naturalLanguageJoin(self::SUPPORTED_OPERATORS),
\gettype($operator).'#'.$operator \gettype($operator).'#'.$operator
@ -386,7 +386,7 @@ $array = [
if (!\in_array($value, self::$allowedValues, true)) { if (!\in_array($value, self::$allowedValues, true)) {
throw new InvalidOptionsException( throw new InvalidOptionsException(
sprintf( \sprintf(
'Unexpected value for operator "%s", expected any of %s, got "%s".', 'Unexpected value for operator "%s", expected any of %s, got "%s".',
$operator, $operator,
Utils::naturalLanguageJoin(array_map( Utils::naturalLanguageJoin(array_map(
@ -631,7 +631,7 @@ $array = [
&& ('=' !== $content || !$this->isEqualPartOfDeclareStatement($tokens, $index)) && ('=' !== $content || !$this->isEqualPartOfDeclareStatement($tokens, $index))
&& $newLineFoundSinceLastPlaceholder && $newLineFoundSinceLastPlaceholder
) { ) {
$tokens[$index] = new Token(sprintf(self::ALIGN_PLACEHOLDER, $this->currentLevel).$content); $tokens[$index] = new Token(\sprintf(self::ALIGN_PLACEHOLDER, $this->currentLevel).$content);
$newLineFoundSinceLastPlaceholder = false; $newLineFoundSinceLastPlaceholder = false;
continue; continue;
@ -764,7 +764,7 @@ $array = [
++$this->deepestLevel; ++$this->deepestLevel;
++$this->currentLevel; ++$this->currentLevel;
} }
$tokenContent = sprintf(self::ALIGN_PLACEHOLDER, $this->currentLevel).$token->getContent(); $tokenContent = \sprintf(self::ALIGN_PLACEHOLDER, $this->currentLevel).$token->getContent();
$nextToken = $tokens[$index + 1]; $nextToken = $tokens[$index + 1];
if (!$nextToken->isWhitespace()) { if (!$nextToken->isWhitespace()) {
@ -871,7 +871,7 @@ $array = [
$tmpCode = $tokens->generateCode(); $tmpCode = $tokens->generateCode();
for ($j = 0; $j <= $this->deepestLevel; ++$j) { for ($j = 0; $j <= $this->deepestLevel; ++$j) {
$placeholder = sprintf(self::ALIGN_PLACEHOLDER, $j); $placeholder = \sprintf(self::ALIGN_PLACEHOLDER, $j);
if (!str_contains($tmpCode, $placeholder)) { if (!str_contains($tmpCode, $placeholder)) {
continue; continue;

View File

@ -133,7 +133,7 @@ final class ConcatSpaceFixer extends AbstractFixer implements ConfigurableFixerI
private function fixWhiteSpaceAroundConcatToken(Tokens $tokens, int $index, int $offset): void private function fixWhiteSpaceAroundConcatToken(Tokens $tokens, int $index, int $offset): void
{ {
if (-1 !== $offset && 1 !== $offset) { if (-1 !== $offset && 1 !== $offset) {
throw new \InvalidArgumentException(sprintf( throw new \InvalidArgumentException(\sprintf(
'Expected `-1|1` for "$offset", got "%s"', 'Expected `-1|1` for "$offset", got "%s"',
$offset $offset
)); ));

View File

@ -89,7 +89,7 @@ final class NewWithParenthesesFixer extends AbstractFixer implements Configurabl
->getOption(), ->getOption(),
(new FixerOptionBuilder('anonymous_class', 'Whether anonymous classes should be followed by parentheses.')) (new FixerOptionBuilder('anonymous_class', 'Whether anonymous classes should be followed by parentheses.'))
->setAllowedTypes(['bool']) ->setAllowedTypes(['bool'])
->setDefault(true) ->setDefault(true) // @TODO 4.0: set to `false`
->getOption(), ->getOption(),
]); ]);
} }

View File

@ -356,7 +356,7 @@ final class NoUselessConcatOperatorFixer extends AbstractFixer implements Config
} }
$allowedPatternsForSecondOperand = [ $allowedPatternsForSecondOperand = [
'/^\s.*/', // e.g. " foo", ' bar', " $baz" '/^ .*/', // e.g. " foo", ' bar', " $baz"
'/^-(?!\>)/', // e.g. "-foo", '-bar', "-$baz" '/^-(?!\>)/', // e.g. "-foo", '-bar', "-$baz"
]; ];

View File

@ -18,6 +18,11 @@ use PhpCsFixer\DocBlock\Annotation;
use PhpCsFixer\DocBlock\DocBlock; use PhpCsFixer\DocBlock\DocBlock;
use PhpCsFixer\Fixer\AbstractPhpUnitFixer; use PhpCsFixer\Fixer\AbstractPhpUnitFixer;
use PhpCsFixer\Fixer\AttributeNotation\OrderedAttributesFixer; use PhpCsFixer\Fixer\AttributeNotation\OrderedAttributesFixer;
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
use PhpCsFixer\Fixer\ConfigurableFixerTrait;
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\FixerDefinition\VersionSpecification; use PhpCsFixer\FixerDefinition\VersionSpecification;
@ -31,9 +36,21 @@ use PhpCsFixer\Tokenizer\Tokens;
/** /**
* @author Kuba Werłos <werlos@gmail.com> * @author Kuba Werłos <werlos@gmail.com>
*
* @implements ConfigurableFixerInterface<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration>
*
* @phpstan-type _AutogeneratedInputConfiguration array{
* keep_annotations?: bool
* }
* @phpstan-type _AutogeneratedComputedConfiguration array{
* keep_annotations: bool
* }
*/ */
final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer implements ConfigurableFixerInterface
{ {
/** @use ConfigurableFixerTrait<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration> */
use ConfigurableFixerTrait;
/** @var array<string, string> */ /** @var array<string, string> */
private array $fixingMap; private array $fixingMap;
@ -45,29 +62,29 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
public function getDefinition(): FixerDefinitionInterface public function getDefinition(): FixerDefinitionInterface
{ {
$codeSample = <<<'PHP'
<?php
/**
* @covers \VendorName\Foo
* @internal
*/
final class FooTest extends TestCase {
/**
* @param int $expected
* @param int $actual
* @dataProvider giveMeSomeData
* @requires PHP 8.0
*/
public function testSomething($expected, $actual) {}
}
PHP;
return new FixerDefinition( return new FixerDefinition(
'PHPUnit attributes must be used over their respective PHPDoc-based annotations.', 'PHPUnit attributes must be used over their respective PHPDoc-based annotations.',
[ [
new VersionSpecificCodeSample( new VersionSpecificCodeSample($codeSample, new VersionSpecification(8_00_00)),
<<<'PHP' new VersionSpecificCodeSample($codeSample, new VersionSpecification(8_00_00), ['keep_annotations' => true]),
<?php
/**
* @covers \VendorName\Foo
* @internal
*/
final class FooTest extends TestCase {
/**
* @param int $expected
* @param int $actual
* @dataProvider giveMeSomeData
* @requires PHP 8.0
*/
public function testSomething($expected, $actual) {}
}
PHP,
new VersionSpecification(8_00_00),
),
], ],
); );
} }
@ -87,6 +104,16 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
return 8; return 8;
} }
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('keep_annotations', 'Whether to keep annotations or not. This may be helpful for projects that support PHP before version 8 or PHPUnit before version 10.'))
->setAllowedTypes(['bool'])
->setDefault(false)
->getOption(),
]);
}
protected function applyPhpUnitClassFix(Tokens $tokens, int $startIndex, int $endIndex): void protected function applyPhpUnitClassFix(Tokens $tokens, int $startIndex, int $endIndex): void
{ {
$classIndex = $tokens->getPrevTokenOfKind($startIndex, [[T_CLASS]]); $classIndex = $tokens->getPrevTokenOfKind($startIndex, [[T_CLASS]]);
@ -109,6 +136,7 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
$docBlock = new DocBlock($tokens[$index]->getContent()); $docBlock = new DocBlock($tokens[$index]->getContent());
$presentAttributes = [];
foreach (array_reverse($docBlock->getAnnotations()) as $annotation) { foreach (array_reverse($docBlock->getAnnotations()) as $annotation) {
$annotationName = $annotation->getTag()->getName(); $annotationName = $annotation->getTag()->getName();
@ -122,7 +150,11 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
/** @phpstan-ignore-next-line */ /** @phpstan-ignore-next-line */
$tokensToInsert = self::{$this->fixingMap[$annotationName]}($tokens, $index, $annotation); $tokensToInsert = self::{$this->fixingMap[$annotationName]}($tokens, $index, $annotation);
if (self::isAttributeAlreadyPresent($tokens, $index, $tokensToInsert)) { if (!isset($presentAttributes[$annotationName])) {
$presentAttributes[$annotationName] = self::isAttributeAlreadyPresent($tokens, $index, $tokensToInsert);
}
if ($presentAttributes[$annotationName]) {
continue; continue;
} }
@ -131,7 +163,10 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
} }
$tokens->insertSlices([$index + 1 => $tokensToInsert]); $tokens->insertSlices([$index + 1 => $tokensToInsert]);
$annotation->remove();
if (!$this->configuration['keep_annotations']) {
$annotation->remove();
}
} }
if ('' === $docBlock->getContent()) { if ('' === $docBlock->getContent()) {
@ -262,7 +297,7 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
private static function fixWithSingleStringValue(Tokens $tokens, int $index, Annotation $annotation): array private static function fixWithSingleStringValue(Tokens $tokens, int $index, Annotation $annotation): array
{ {
Preg::match( Preg::match(
sprintf('/@%s\s+(.*\S)(?:\R|\s*\*+\/$)/', $annotation->getTag()->getName()), \sprintf('/@%s\s+(.*\S)(?:\R|\s*\*+\/$)/', $annotation->getTag()->getName()),
$annotation->getContent(), $annotation->getContent(),
$matches, $matches,
); );
@ -302,6 +337,7 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
private static function fixCovers(Tokens $tokens, int $index, Annotation $annotation): array private static function fixCovers(Tokens $tokens, int $index, Annotation $annotation): array
{ {
$matches = self::getMatches($annotation); $matches = self::getMatches($annotation);
\assert(isset($matches[1]));
if (str_starts_with($matches[1], '::')) { if (str_starts_with($matches[1], '::')) {
return self::createAttributeTokens($tokens, $index, 'CoversFunction', self::createEscapedStringToken(substr($matches[1], 2))); return self::createAttributeTokens($tokens, $index, 'CoversFunction', self::createEscapedStringToken(substr($matches[1], 2)));
@ -329,6 +365,7 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
} }
if (str_contains($matches[1], '::')) { if (str_contains($matches[1], '::')) {
// @phpstan-ignore offsetAccess.notFound
[$class, $method] = explode('::', $matches[1]); [$class, $method] = explode('::', $matches[1]);
return self::createAttributeTokens( return self::createAttributeTokens(
@ -372,7 +409,9 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
$class = null; $class = null;
$method = $depended; $method = $depended;
if (str_contains($depended, '::')) { if (str_contains($depended, '::')) {
// @phpstan-ignore offsetAccess.notFound
[$class, $method] = explode('::', $depended); [$class, $method] = explode('::', $depended);
if ('class' === $method) { if ('class' === $method) {
$method = null; $method = null;
$nameSuffix = '' === $nameSuffix ? 'OnClass' : ('OnClass'.$nameSuffix); $nameSuffix = '' === $nameSuffix ? 'OnClass' : ('OnClass'.$nameSuffix);
@ -402,6 +441,7 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
private static function fixRequires(Tokens $tokens, int $index, Annotation $annotation): array private static function fixRequires(Tokens $tokens, int $index, Annotation $annotation): array
{ {
$matches = self::getMatches($annotation); $matches = self::getMatches($annotation);
\assert(isset($matches[1]));
$map = [ $map = [
'extension' => 'RequiresPhpExtension', 'extension' => 'RequiresPhpExtension',
@ -420,9 +460,12 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
$attributeName = $map[$matches[1]]; $attributeName = $map[$matches[1]];
if ('RequiresFunction' === $attributeName && str_contains($matches[2], '::')) { if ('RequiresFunction' === $attributeName && str_contains($matches[2], '::')) {
// @phpstan-ignore offsetAccess.notFound
[$class, $method] = explode('::', $matches[2]); [$class, $method] = explode('::', $matches[2]);
$attributeName = 'RequiresMethod'; $attributeName = 'RequiresMethod';
$attributeTokens = [...self::toClassConstant($class), $attributeTokens = [
...self::toClassConstant($class),
new Token(','), new Token(','),
new Token([T_WHITESPACE, ' ']), new Token([T_WHITESPACE, ' ']),
self::createEscapedStringToken($method), self::createEscapedStringToken($method),
@ -495,7 +538,7 @@ final class PhpUnitAttributesFixer extends AbstractPhpUnitFixer
private static function getMatches(Annotation $annotation): array private static function getMatches(Annotation $annotation): array
{ {
Preg::match( Preg::match(
sprintf('/@%s\s+(\S+)(?:\s+(\S+))?(?:\s+(.+\S))?\s*(?:\R|\*+\/$)/', $annotation->getTag()->getName()), \sprintf('/@%s\s+(\S+)(?:\s+(\S+))?(?:\s+(.+\S))?\s*(?:\R|\*+\/$)/', $annotation->getTag()->getName()),
$annotation->getContent(), $annotation->getContent(),
$matches, $matches,
); );

View File

@ -163,8 +163,8 @@ class FooTest extends TestCase {
$tokens[$dataProviderAnalysis->getNameIndex()] = new Token([T_STRING, $dataProviderNewName]); $tokens[$dataProviderAnalysis->getNameIndex()] = new Token([T_STRING, $dataProviderNewName]);
$newCommentContent = Preg::replace( $newCommentContent = Preg::replace(
sprintf('/(@dataProvider\s+)%s/', $dataProviderAnalysis->getName()), \sprintf('/(@dataProvider\s+)%s/', $dataProviderAnalysis->getName()),
sprintf('$1%s', $dataProviderNewName), \sprintf('$1%s', $dataProviderNewName),
$tokens[$usageIndex]->getContent(), $tokens[$usageIndex]->getContent(),
); );

View File

@ -24,7 +24,6 @@ use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition; use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface; use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer; use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer;
use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer;
use PhpCsFixer\Tokenizer\CT; use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Token; use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens; use PhpCsFixer\Tokenizer\Tokens;
@ -171,7 +170,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
/** /**
* {@inheritdoc} * {@inheritdoc}
* *
* Must run before NoUnusedImportsFixer, PhpUnitDedicateAssertInternalTypeFixer. * Must run before NoUnusedImportsFixer, PhpUnitAssertNewNamesFixer, PhpUnitDedicateAssertInternalTypeFixer.
* Must run after ModernizeStrposFixer, NoAliasFunctionsFixer, PhpUnitConstructFixer. * Must run after ModernizeStrposFixer, NoAliasFunctionsFixer, PhpUnitConstructFixer.
*/ */
public function getPriority(): int public function getPriority(): int
@ -241,21 +240,18 @@ final class MyTest extends \PHPUnit_Framework_TestCase
foreach ($this->getPreviousAssertCall($tokens, $startIndex, $endIndex) as $assertCall) { foreach ($this->getPreviousAssertCall($tokens, $startIndex, $endIndex) as $assertCall) {
// test and fix for assertTrue/False to dedicated asserts // test and fix for assertTrue/False to dedicated asserts
if ('asserttrue' === $assertCall['loweredName'] || 'assertfalse' === $assertCall['loweredName']) { if (\in_array($assertCall['loweredName'], ['asserttrue', 'assertfalse'], true)) {
$this->fixAssertTrueFalse($tokens, $argumentsAnalyzer, $assertCall); $this->fixAssertTrueFalse($tokens, $argumentsAnalyzer, $assertCall);
continue; continue;
} }
if ( if (\in_array(
'assertsame' === $assertCall['loweredName'] $assertCall['loweredName'],
|| 'assertnotsame' === $assertCall['loweredName'] ['assertsame', 'assertnotsame', 'assertequals', 'assertnotequals'],
|| 'assertequals' === $assertCall['loweredName'] true
|| 'assertnotequals' === $assertCall['loweredName'] )) {
) {
$this->fixAssertSameEquals($tokens, $assertCall); $this->fixAssertSameEquals($tokens, $assertCall);
continue;
} }
} }
} }
@ -495,7 +491,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
$lowerContent = strtolower($tokens[$countCallIndex]->getContent()); $lowerContent = strtolower($tokens[$countCallIndex]->getContent());
if ('count' !== $lowerContent && 'sizeof' !== $lowerContent) { if (!\in_array($lowerContent, ['count', 'sizeof'], true)) {
return; // not a call to "count" or "sizeOf" return; // not a call to "count" or "sizeOf"
} }
@ -527,52 +523,6 @@ final class MyTest extends \PHPUnit_Framework_TestCase
]); ]);
} }
/**
* @return iterable<array{
* index: int,
* loweredName: string,
* openBraceIndex: int,
* closeBraceIndex: int,
* }>
*/
private function getPreviousAssertCall(Tokens $tokens, int $startIndex, int $endIndex): iterable
{
$functionsAnalyzer = new FunctionsAnalyzer();
for ($index = $endIndex; $index > $startIndex; --$index) {
$index = $tokens->getPrevTokenOfKind($index, [[T_STRING]]);
if (null === $index) {
return;
}
// test if "assert" something call
$loweredContent = strtolower($tokens[$index]->getContent());
if (!str_starts_with($loweredContent, 'assert')) {
continue;
}
// test candidate for simple calls like: ([\]+'some fixable call'(...))
$openBraceIndex = $tokens->getNextMeaningfulToken($index);
if (!$tokens[$openBraceIndex]->equals('(')) {
continue;
}
if (!$functionsAnalyzer->isTheSameClassCall($tokens, $index)) {
continue;
}
yield [
'index' => $index,
'loweredName' => $loweredContent,
'openBraceIndex' => $openBraceIndex,
'closeBraceIndex' => $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openBraceIndex),
];
}
}
private function removeFunctionCall(Tokens $tokens, ?int $callNSIndex, int $callIndex, int $openIndex, int $closeIndex): void private function removeFunctionCall(Tokens $tokens, ?int $callNSIndex, int $callIndex, int $openIndex, int $closeIndex): void
{ {
$tokens->clearTokenAndMergeSurroundingWhitespace($callIndex); $tokens->clearTokenAndMergeSurroundingWhitespace($callIndex);

View File

@ -230,6 +230,10 @@ final class MyTest extends \PHPUnit_Framework_TestCase
$argStart = array_keys($arguments)[$cnt]; $argStart = array_keys($arguments)[$cnt];
$argBefore = $tokens->getPrevMeaningfulToken($argStart); $argBefore = $tokens->getPrevMeaningfulToken($argStart);
if (!isset($argumentsReplacements[$cnt])) {
throw new \LogicException(\sprintf('Unexpected index %d to find replacement method.', $cnt));
}
if ('expectExceptionMessage' === $argumentsReplacements[$cnt]) { if ('expectExceptionMessage' === $argumentsReplacements[$cnt]) {
$paramIndicatorIndex = $tokens->getNextMeaningfulToken($argBefore); $paramIndicatorIndex = $tokens->getNextMeaningfulToken($argBefore);
$afterParamIndicatorIndex = $tokens->getNextMeaningfulToken($paramIndicatorIndex); $afterParamIndicatorIndex = $tokens->getNextMeaningfulToken($paramIndicatorIndex);

View File

@ -188,7 +188,7 @@ class MyTest extends \PhpUnit\FrameWork\TestCase
continue; continue;
} }
$newLineContent = Preg::replaceCallback('/(@depends\s+)(.+)(\b)/', fn (array $matches): string => sprintf( $newLineContent = Preg::replaceCallback('/(@depends\s+)(.+)(\b)/', fn (array $matches): string => \sprintf(
'%s%s%s', '%s%s%s',
$matches[1], $matches[1],
$this->updateMethodCasing($matches[2]), $this->updateMethodCasing($matches[2]),

View File

@ -37,6 +37,7 @@ final class PhpUnitTargetVersion
public const VERSION_6_0 = '6.0'; public const VERSION_6_0 = '6.0';
public const VERSION_7_5 = '7.5'; public const VERSION_7_5 = '7.5';
public const VERSION_8_4 = '8.4'; public const VERSION_8_4 = '8.4';
public const VERSION_9_1 = '9.1';
public const VERSION_NEWEST = 'newest'; public const VERSION_NEWEST = 'newest';
private function __construct() {} private function __construct() {}
@ -44,7 +45,7 @@ final class PhpUnitTargetVersion
public static function fulfills(string $candidate, string $target): bool public static function fulfills(string $candidate, string $target): bool
{ {
if (self::VERSION_NEWEST === $target) { if (self::VERSION_NEWEST === $target) {
throw new \LogicException(sprintf('Parameter `target` shall not be provided as "%s", determine proper target for tested PHPUnit feature instead.', self::VERSION_NEWEST)); throw new \LogicException(\sprintf('Parameter `target` shall not be provided as "%s", determine proper target for tested PHPUnit feature instead.', self::VERSION_NEWEST));
} }
if (self::VERSION_NEWEST === $candidate) { if (self::VERSION_NEWEST === $candidate) {

View File

@ -393,7 +393,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
foreach ($option as $method => $value) { foreach ($option as $method => $value) {
if (!isset(self::STATIC_METHODS[$method])) { if (!isset(self::STATIC_METHODS[$method])) {
throw new InvalidOptionsException( throw new InvalidOptionsException(
sprintf( \sprintf(
'Unexpected "methods" key, expected any of %s, got "%s".', 'Unexpected "methods" key, expected any of %s, got "%s".',
Utils::naturalLanguageJoin(array_keys(self::STATIC_METHODS)), Utils::naturalLanguageJoin(array_keys(self::STATIC_METHODS)),
\gettype($method).'#'.$method \gettype($method).'#'.$method
@ -403,7 +403,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
if (!isset(self::ALLOWED_VALUES[$value])) { if (!isset(self::ALLOWED_VALUES[$value])) {
throw new InvalidOptionsException( throw new InvalidOptionsException(
sprintf( \sprintf(
'Unexpected value for method "%s", expected any of %s, got "%s".', 'Unexpected value for method "%s", expected any of %s, got "%s".',
$method, $method,
Utils::naturalLanguageJoin(array_keys(self::ALLOWED_VALUES)), Utils::naturalLanguageJoin(array_keys(self::ALLOWED_VALUES)),

View File

@ -121,7 +121,7 @@ final class GeneralPhpdocTagRenameFixer extends AbstractFixer implements Configu
} }
if (!Preg::match('#^\S+$#', $to) || str_contains($to, '*/')) { if (!Preg::match('#^\S+$#', $to) || str_contains($to, '*/')) {
throw new InvalidOptionsException(sprintf( throw new InvalidOptionsException(\sprintf(
'Tag "%s" cannot be replaced by invalid tag "%s".', 'Tag "%s" cannot be replaced by invalid tag "%s".',
$from, $from,
$to $to
@ -135,7 +135,7 @@ final class GeneralPhpdocTagRenameFixer extends AbstractFixer implements Configu
$lowercaseFrom = strtolower($from); $lowercaseFrom = strtolower($from);
if (isset($normalizedValue[$lowercaseFrom]) && $normalizedValue[$lowercaseFrom] !== $to) { if (isset($normalizedValue[$lowercaseFrom]) && $normalizedValue[$lowercaseFrom] !== $to) {
throw new InvalidOptionsException(sprintf( throw new InvalidOptionsException(\sprintf(
'Tag "%s" cannot be configured to be replaced with several different tags when case sensitivity is off.', 'Tag "%s" cannot be configured to be replaced with several different tags when case sensitivity is off.',
$from $from
)); ));
@ -149,7 +149,7 @@ final class GeneralPhpdocTagRenameFixer extends AbstractFixer implements Configu
foreach ($normalizedValue as $from => $to) { foreach ($normalizedValue as $from => $to) {
if (isset($normalizedValue[$to]) && $normalizedValue[$to] !== $to) { if (isset($normalizedValue[$to]) && $normalizedValue[$to] !== $to) {
throw new InvalidOptionsException(sprintf( throw new InvalidOptionsException(\sprintf(
'Cannot change tag "%1$s" to tag "%2$s", as the tag "%2$s" is configured to be replaced to "%3$s".', 'Cannot change tag "%1$s" to tag "%2$s", as the tag "%2$s" is configured to be replaced to "%3$s".',
$from, $from,
$to, $to,
@ -185,7 +185,7 @@ final class GeneralPhpdocTagRenameFixer extends AbstractFixer implements Configu
$caseInsensitive = false === $this->configuration['case_sensitive']; $caseInsensitive = false === $this->configuration['case_sensitive'];
$replacements = $this->configuration['replacements']; $replacements = $this->configuration['replacements'];
$regex = sprintf($regex, implode('|', array_keys($replacements))); $regex = \sprintf($regex, implode('|', array_keys($replacements)));
if ($caseInsensitive) { if ($caseInsensitive) {
$regex .= 'i'; $regex .= 'i';

View File

@ -620,7 +620,10 @@ class Foo {
// retry comparison with annotation type unioned with null // retry comparison with annotation type unioned with null
// phpstan implies the null presence from the native type // phpstan implies the null presence from the native type
return $actualTypes === $this->toComparableNames(array_merge($annotationTypes, ['null']), null, null, []); $annotationTypes = array_merge($annotationTypes, ['null']);
sort($annotationTypes);
return $actualTypes === $annotationTypes;
} }
/** /**
@ -637,6 +640,13 @@ class Foo {
*/ */
private function toComparableNames(array $types, ?string $namespace, ?string $currentSymbol, array $symbolShortNames): array private function toComparableNames(array $types, ?string $namespace, ?string $currentSymbol, array $symbolShortNames): array
{ {
if (isset($types[0][0]) && '?' === $types[0][0]) {
$types = [
substr($types[0], 1),
'null',
];
}
$normalized = array_map( $normalized = array_map(
function (string $type) use ($namespace, $currentSymbol, $symbolShortNames): string { function (string $type) use ($namespace, $currentSymbol, $symbolShortNames): string {
if (str_contains($type, '&')) { if (str_contains($type, '&')) {

View File

@ -199,7 +199,7 @@ function f9(string $foo, $bar, $baz) {}
$type = 'null|'.$type; $type = 'null|'.$type;
} }
$newLines[] = new Line(sprintf( $newLines[] = new Line(\sprintf(
'%s* @param %s %s%s', '%s* @param %s %s%s',
$indent, $indent,
$type, $type,

View File

@ -106,7 +106,7 @@ function foo ($bar) {}
$startLine = $doc->getLine($annotation->getStart()); $startLine = $doc->getLine($annotation->getStart());
$optionalTypeRegEx = $annotation->supportTypes() $optionalTypeRegEx = $annotation->supportTypes()
? sprintf('(?:%s\s+(?:\$\w+\s+)?)?', preg_quote(implode('|', $annotation->getTypes()), '/')) ? \sprintf('(?:%s\s+(?:\$\w+\s+)?)?', preg_quote(implode('|', $annotation->getTypes()), '/'))
: ''; : '';
$content = Preg::replaceCallback( $content = Preg::replaceCallback(
'/^(\s*\*\s*@\w+\s+'.$optionalTypeRegEx.')(\p{Lu}?(?=\p{Ll}|\p{Zs}))(.*)$/', '/^(\s*\*\s*@\w+\s+'.$optionalTypeRegEx.')(\p{Lu}?(?=\p{Ll}|\p{Zs}))(.*)$/',

View File

@ -63,7 +63,9 @@ class DocBlocks
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{ {
foreach ($tokens as $index => $token) { for ($index = $tokens->count() - 1; 0 <= $index; --$index) {
$token = $tokens[$index];
if (!$token->isGivenKind(T_DOC_COMMENT)) { if (!$token->isGivenKind(T_DOC_COMMENT)) {
continue; continue;
} }
@ -95,7 +97,13 @@ class DocBlocks
$newPrevContent = $this->fixWhitespaceBeforeDocblock($prevToken->getContent(), $indent); $newPrevContent = $this->fixWhitespaceBeforeDocblock($prevToken->getContent(), $indent);
if ('' !== $newPrevContent) { $tokens[$index] = new Token([T_DOC_COMMENT, $this->fixDocBlock($token->getContent(), $indent)]);
if (!$prevToken->isWhitespace()) {
if ('' !== $indent) {
$tokens->insertAt($index, new Token([T_WHITESPACE, $indent]));
}
} elseif ('' !== $newPrevContent) {
if ($prevToken->isArray()) { if ($prevToken->isArray()) {
$tokens[$prevIndex] = new Token([$prevToken->getId(), $newPrevContent]); $tokens[$prevIndex] = new Token([$prevToken->getId(), $newPrevContent]);
} else { } else {
@ -104,8 +112,6 @@ class DocBlocks
} else { } else {
$tokens->clearAt($prevIndex); $tokens->clearAt($prevIndex);
} }
$tokens[$index] = new Token([T_DOC_COMMENT, $this->fixDocBlock($token->getContent(), $indent)]);
} }
} }

View File

@ -89,7 +89,7 @@ final class PhpdocInlineTagNormalizerFixer extends AbstractFixer implements Conf
// remove spaces between '{' and '@', remove white space between end // remove spaces between '{' and '@', remove white space between end
// of text and closing bracket and between the tag and inline comment. // of text and closing bracket and between the tag and inline comment.
$content = Preg::replaceCallback( $content = Preg::replaceCallback(
sprintf( \sprintf(
'#(?:@{+|{+\h*@)\h*(%s)\b([^}]*)(?:}+)#i', '#(?:@{+|{+\h*@)\h*(%s)\b([^}]*)(?:}+)#i',
implode('|', array_map(static fn (string $tag): string => preg_quote($tag, '/'), $this->configuration['tags'])) implode('|', array_map(static fn (string $tag): string => preg_quote($tag, '/'), $this->configuration['tags']))
), ),

View File

@ -106,7 +106,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
for ($index = $tokens->count() - 1; $index > 0; --$index) { for ($index = $tokens->count() - 1; $index > 0; --$index) {
foreach ($this->configuration['annotations'] as $type => $typeLowerCase) { foreach ($this->configuration['annotations'] as $type => $typeLowerCase) {
$findPattern = sprintf( $findPattern = \sprintf(
'/@%s\s.+@%s\s/s', '/@%s\s.+@%s\s/s',
$type, $type,
$type $type
@ -125,7 +125,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
$annotationMap = []; $annotationMap = [];
if (\in_array($type, ['property', 'property-read', 'property-write'], true)) { if (\in_array($type, ['property', 'property-read', 'property-write'], true)) {
$replacePattern = sprintf( $replacePattern = \sprintf(
'/(?s)\*\s*@%s\s+(?P<optionalTypes>.+\s+)?\$(?P<comparableContent>\S+).*/', '/(?s)\*\s*@%s\s+(?P<optionalTypes>.+\s+)?\$(?P<comparableContent>\S+).*/',
$type $type
); );
@ -135,7 +135,7 @@ final class MyTest extends \PHPUnit_Framework_TestCase
$replacePattern = '/(?s)\*\s*@method\s+(?P<optionalReturnTypes>.+\s+)?(?P<comparableContent>.+)\(.*/'; $replacePattern = '/(?s)\*\s*@method\s+(?P<optionalReturnTypes>.+\s+)?(?P<comparableContent>.+)\(.*/';
$replacement = '\2'; $replacement = '\2';
} else { } else {
$replacePattern = sprintf( $replacePattern = \sprintf(
'/\*\s*@%s\s+(?P<comparableContent>.+)/', '/\*\s*@%s\s+(?P<comparableContent>.+)/',
$typeLowerCase $typeLowerCase
); );

View File

@ -159,7 +159,7 @@ class Sample
} }
if (!isset($default[$from])) { if (!isset($default[$from])) {
throw new InvalidOptionsException(sprintf( throw new InvalidOptionsException(\sprintf(
'Unknown key "%s", expected any of %s.', 'Unknown key "%s", expected any of %s.',
\gettype($from).'#'.$from, \gettype($from).'#'.$from,
Utils::naturalLanguageJoin(array_keys($default)) Utils::naturalLanguageJoin(array_keys($default))
@ -167,7 +167,7 @@ class Sample
} }
if (!\in_array($to, self::$toTypes, true)) { if (!\in_array($to, self::$toTypes, true)) {
throw new InvalidOptionsException(sprintf( throw new InvalidOptionsException(\sprintf(
'Unknown value "%s", expected any of %s.', 'Unknown value "%s", expected any of %s.',
\is_object($to) ? \get_class($to) : \gettype($to).(\is_resource($to) ? '' : '#'.$to), \is_object($to) ? \get_class($to) : \gettype($to).(\is_resource($to) ? '' : '#'.$to),
Utils::naturalLanguageJoin(self::$toTypes) Utils::naturalLanguageJoin(self::$toTypes)

View File

@ -44,10 +44,8 @@ final class PhpdocScalarFixer extends AbstractPhpdocTypesFixer implements Config
/** /**
* The types to fix. * The types to fix.
*
* @var array<string, string>
*/ */
private static array $types = [ private const TYPES_MAP = [
'boolean' => 'bool', 'boolean' => 'bool',
'callback' => 'callable', 'callback' => 'callable',
'double' => 'float', 'double' => 'float',
@ -114,7 +112,7 @@ function sample($a, $b, $c)
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
{ {
$types = array_keys(self::$types); $types = array_keys(self::TYPES_MAP);
return new FixerConfigurationResolver([ return new FixerConfigurationResolver([
(new FixerOptionBuilder('types', 'A list of types to fix.')) (new FixerOptionBuilder('types', 'A list of types to fix.'))
@ -133,7 +131,7 @@ function sample($a, $b, $c)
} }
if (\in_array($type, $this->configuration['types'], true)) { if (\in_array($type, $this->configuration['types'], true)) {
$type = self::$types[$type]; $type = self::TYPES_MAP[$type];
} }
return $type.$suffix; return $type.$suffix;

View File

@ -92,7 +92,7 @@ final class PhpdocTagTypeFixer extends AbstractFixer implements ConfigurableFixe
return; return;
} }
$regularExpression = sprintf( $regularExpression = \sprintf(
'/({?@(?:%s).*?(?:(?=\s\*\/)|(?=\n)}?))/i', '/({?@(?:%s).*?(?:(?=\s\*\/)|(?=\n)}?))/i',
implode('|', array_map( implode('|', array_map(
static fn (string $tag): string => preg_quote($tag, '/'), static fn (string $tag): string => preg_quote($tag, '/'),

View File

@ -64,10 +64,10 @@ final class FixerConfigurationResolver implements FixerConfigurationResolverInte
if (\array_key_exists($alias, $configuration)) { if (\array_key_exists($alias, $configuration)) {
if (\array_key_exists($name, $configuration)) { if (\array_key_exists($name, $configuration)) {
throw new InvalidOptionsException(sprintf('Aliased option "%s"/"%s" is passed multiple times.', $name, $alias)); throw new InvalidOptionsException(\sprintf('Aliased option "%s"/"%s" is passed multiple times.', $name, $alias));
} }
Utils::triggerDeprecation(new \RuntimeException(sprintf( Utils::triggerDeprecation(new \RuntimeException(\sprintf(
'Option "%s" is deprecated, use "%s" instead.', 'Option "%s" is deprecated, use "%s" instead.',
$alias, $alias,
$name $name
@ -138,7 +138,7 @@ final class FixerConfigurationResolver implements FixerConfigurationResolverInte
$name = $option->getName(); $name = $option->getName();
if (\in_array($name, $this->registeredNames, true)) { if (\in_array($name, $this->registeredNames, true)) {
throw new \LogicException(sprintf('The "%s" option is defined multiple times.', $name)); throw new \LogicException(\sprintf('The "%s" option is defined multiple times.', $name));
} }
$this->options[] = $option; $this->options[] = $option;

View File

@ -132,11 +132,11 @@ final class FixerFactory
$name = $fixer->getName(); $name = $fixer->getName();
if (isset($this->fixersByName[$name])) { if (isset($this->fixersByName[$name])) {
throw new \UnexpectedValueException(sprintf('Fixer named "%s" is already registered.', $name)); throw new \UnexpectedValueException(\sprintf('Fixer named "%s" is already registered.', $name));
} }
if (!$this->nameValidator->isValid($name, $isCustom)) { if (!$this->nameValidator->isValid($name, $isCustom)) {
throw new \UnexpectedValueException(sprintf('Fixer named "%s" has invalid name.', $name)); throw new \UnexpectedValueException(\sprintf('Fixer named "%s" has invalid name.', $name));
} }
$this->fixers[] = $fixer; $this->fixers[] = $fixer;
@ -159,7 +159,7 @@ final class FixerFactory
$fixerNames = array_keys($ruleSet->getRules()); $fixerNames = array_keys($ruleSet->getRules());
foreach ($fixerNames as $name) { foreach ($fixerNames as $name) {
if (!\array_key_exists($name, $this->fixersByName)) { if (!\array_key_exists($name, $this->fixersByName)) {
throw new \UnexpectedValueException(sprintf('Rule "%s" does not exist.', $name)); throw new \UnexpectedValueException(\sprintf('Rule "%s" does not exist.', $name));
} }
$fixer = $this->fixersByName[$name]; $fixer = $this->fixersByName[$name];
@ -239,7 +239,7 @@ final class FixerFactory
); );
if (\count($report[$fixer]) > 0) { if (\count($report[$fixer]) > 0) {
$message .= sprintf("\n- \"%s\" with %s", $fixer, Utils::naturalLanguageJoin($report[$fixer])); $message .= \sprintf("\n- \"%s\" with %s", $fixer, Utils::naturalLanguageJoin($report[$fixer]));
} }
} }

View File

@ -25,7 +25,7 @@ final class PhpUnitTestCaseIndicator
public function isPhpUnitClass(Tokens $tokens, int $index): bool public function isPhpUnitClass(Tokens $tokens, int $index): bool
{ {
if (!$tokens[$index]->isGivenKind(T_CLASS)) { if (!$tokens[$index]->isGivenKind(T_CLASS)) {
throw new \LogicException(sprintf('No "T_CLASS" at given index %d, got "%s".', $index, $tokens[$index]->getName())); throw new \LogicException(\sprintf('No "T_CLASS" at given index %d, got "%s".', $index, $tokens[$index]->getName()));
} }
$index = $tokens->getNextMeaningfulToken($index); $index = $tokens->getNextMeaningfulToken($index);

View File

@ -143,7 +143,7 @@ final class ProcessLinter implements LinterInterface
} }
if (false === @file_put_contents($this->temporaryFile, $source)) { if (false === @file_put_contents($this->temporaryFile, $source)) {
throw new IOException(sprintf('Failed to write file "%s".', $this->temporaryFile), 0, null, $this->temporaryFile); throw new IOException(\sprintf('Failed to write file "%s".', $this->temporaryFile), 0, null, $this->temporaryFile);
} }
return $this->createProcessForFile($this->temporaryFile); return $this->createProcessForFile($this->temporaryFile);

View File

@ -53,25 +53,25 @@ final class ProcessLintingResult implements LintingResultInterface
} }
if (null !== $this->path) { if (null !== $this->path) {
$needle = sprintf('in %s ', $this->path); $needle = \sprintf('in %s ', $this->path);
$pos = strrpos($output, $needle); $pos = strrpos($output, $needle);
if (false !== $pos) { if (false !== $pos) {
$output = sprintf('%s%s', substr($output, 0, $pos), substr($output, $pos + \strlen($needle))); $output = \sprintf('%s%s', substr($output, 0, $pos), substr($output, $pos + \strlen($needle)));
} }
} }
$prefix = substr($output, 0, 18); $prefix = substr($output, 0, 18);
if ('PHP Parse error: ' === $prefix) { if ('PHP Parse error: ' === $prefix) {
return sprintf('Parse error: %s.', substr($output, 18)); return \sprintf('Parse error: %s.', substr($output, 18));
} }
if ('PHP Fatal error: ' === $prefix) { if ('PHP Fatal error: ' === $prefix) {
return sprintf('Fatal error: %s.', substr($output, 18)); return \sprintf('Fatal error: %s.', substr($output, 18));
} }
return sprintf('%s.', $output); return \sprintf('%s.', $output);
} }
private function isSuccessful(): bool private function isSuccessful(): bool

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