extrac prices pdfco

This commit is contained in:
Claudio 2025-11-17 15:05:10 +01:00
parent 6b65b31932
commit 1804605cad
16 changed files with 1131 additions and 330 deletions

View File

@ -108,9 +108,9 @@ class LoginController extends Controller
// Reindirizza in base al ruolo
if ($user->hasRole('Admin')) {
return redirect()->to('userarea/import_dashboard.php');
return redirect()->to('userarea/import_xls.php');
} elseif ($user->hasRole('User')) {
return redirect()->to('userarea/import_dashboard.php');
return redirect()->to('userarea/import_xls.php');
}
// Se il ruolo non è specificato, reindirizza alla home predefinita

View File

@ -47,6 +47,7 @@
"smalot/pdfparser": "^2.12",
"socialiteproviders/microsoft": "^4.7",
"spatie/laravel-query-builder": "^5.0",
"spatie/pdf-to-text": "^1.54",
"vanguardapp/activity-log": "^6.0",
"vanguardapp/announcements": "^6.0",
"vanguardapp/plugins": "^6.0",

60
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "97382155de516648df8ab1f1c50ab1d5",
"content-hash": "d55364bafa22e40dedff454d54442d59",
"packages": [
{
"name": "akaunting/laravel-setting",
@ -5290,6 +5290,64 @@
],
"time": "2024-05-10T08:19:35+00:00"
},
{
"name": "spatie/pdf-to-text",
"version": "1.54.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/pdf-to-text.git",
"reference": "ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/pdf-to-text/zipball/ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb",
"reference": "ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb",
"shasum": ""
},
"require": {
"php": "^7.4|^8.0",
"symfony/process": "^4.0|^5.0|^6.0|^7.0"
},
"require-dev": {
"pestphp/pest-plugin-laravel": "^1.3",
"phpunit/phpunit": "^9.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Spatie\\PdfToText\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Freek Van der Herten",
"email": "freek@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
}
],
"description": "Extract text from a pdf",
"homepage": "https://github.com/spatie/pdf-to-text",
"keywords": [
"pdf-to-text",
"spatie"
],
"support": {
"issues": "https://github.com/spatie/pdf-to-text/issues",
"source": "https://github.com/spatie/pdf-to-text/tree/1.54.1"
},
"funding": [
{
"url": "https://spatie.be/open-source/support-us",
"type": "custom"
}
],
"time": "2025-06-13T15:23:19+00:00"
},
{
"name": "symfony/clock",
"version": "v7.1.1",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -0,0 +1,73 @@
<?php
require_once __DIR__ . "/../../vendor/autoload.php";
use Spatie\PdfToText\Pdf;
// ---------------------------------------------------------
// 1) Percorso PDF
// ---------------------------------------------------------
$pdfFile = __DIR__ . "/listino.pdf";
if (!file_exists($pdfFile)) {
die(json_encode(["error" => "PDF non trovato: $pdfFile"]));
}
// ---------------------------------------------------------
// 2) Estrazione testo usando Poppler
// ---------------------------------------------------------
$poppler = 'C:\poppler\Library\bin\pdftotext.exe';
try {
$text = Pdf::getText($pdfFile, $poppler);
} catch (Exception $e) {
die(json_encode(["error" => $e->getMessage()]));
}
// ---------------------------------------------------------
// 3) Normalizzazione
// ---------------------------------------------------------
$text = preg_replace('/[ ]{2,}/', ' ', $text);
$text = str_replace("\t", " ", $text);
// ---------------------------------------------------------
// 4) REGEX PER IL LISTINO CASSINA
// ---------------------------------------------------------
$regex = '/(\d{3}\s+\d{2,3}\s*[A-Z]?)\s+([^0-9]+?)\s+((?:\d{1,2}[.,]\d{2,3}\s+)+)/';
preg_match_all($regex, $text, $matches, PREG_SET_ORDER);
$results = [];
foreach ($matches as $m) {
$codice = trim($m[1]);
$descr = trim($m[2]);
$priceChunk = trim($m[3]);
// Trova tutti i prezzi
preg_match_all('/\d{1,2}[.,]\d{2,3}/', $priceChunk, $nums);
foreach ($nums[0] as $i => $val) {
// 10,80 → 10.80
$val = str_replace(',', '.', $val);
$results[] = [
"codice" => $codice,
"descrizione" => $descr,
"colonna" => "COL_" . ($i + 1),
"prezzo" => floatval($val)
];
}
}
// ---------------------------------------------------------
// 5) Output JSON
// ---------------------------------------------------------
header("Content-Type: application/json");
echo json_encode([
"items" => count($results),
"data" => $results
], JSON_PRETTY_PRINT);

View File

@ -0,0 +1,218 @@
<?php
header("Content-Type: application/json; charset=utf-8");
// ---------------------------------------------------------
// 1) CONFIGURAZIONE
// ---------------------------------------------------------
$apiKey = "info@claudiosironi.com_Qfh02D7sAvi2tcx3ZchHpusNaBquCKhJw81fEnkHe2ersQDVOex4IokhCCzaFAz1";
$fileToken = "filetoken://37bb07a8561409d281b32bcd023ff3dc33de92a8f65aae5af7";
// opzionale: passare un token via GET
if (isset($_GET['token']) && $_GET['token'] !== "") {
$fileToken = $_GET['token'];
}
// ---------------------------------------------------------
// 2) PDF.CO → JSON2
// ---------------------------------------------------------
$endpoint = "https://api.pdf.co/v1/pdf/convert/to/json2";
$payload = [
"url" => $fileToken,
"inline" => true,
"detectTables" => true,
"pages" => ""
];
$ch = curl_init($endpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"x-api-key: $apiKey"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if (!$response) {
echo json_encode(["error" => "Errore CURL: " . curl_error($ch)]);
curl_close($ch);
exit;
}
curl_close($ch);
$json = json_decode($response, true);
if (!isset($json["body"]["document"]["page"]["row"])) {
echo json_encode([
"error" => true,
"message" => "JSON PDF.co non contiene tabelle utili",
"raw" => $json
]);
exit;
}
$rows = $json["body"]["document"]["page"]["row"];
// ---------------------------------------------------------
// 3) FUNZIONI UTILITARIE
// ---------------------------------------------------------
// Formato A 291 02F
function isCodeTypeA($txt)
{
return preg_match('/^\d{3}\s+[0-9A-Z]{2,3}$/', $txt);
}
// Estrai blocchi tipo "499 3A 14 5.475"
function extractTypeCBlocks($line)
{
preg_match_all(
'/(\d{3})\s+([0-9A-Z]{1,3})\s+(\d{2})\s+(\d{1,2}\.\d{3})/',
$line,
$m,
PREG_SET_ORDER
);
$out = [];
foreach ($m as $b) {
$out[] = [
"codice" => $b[1],
"variante" => $b[2],
"dimensione" => $b[3],
"prezzo" => floatval(str_replace(".", "", $b[4]))
];
}
return $out;
}
// ---------------------------------------------------------
// 4) PARSER UNICO (GESTISCE TUTTI I FORMATI)
// ---------------------------------------------------------
$items = [];
$currentCode = null;
$currentDesc = "";
$currentPrices = [];
foreach ($rows as $row) {
// Ricostruisco la riga
$line = "";
foreach ($row["column"] as $col) {
if (!isset($col["text"]["text"])) continue;
$t = trim($col["text"]["text"]);
if ($t !== "") $line .= " " . $t;
}
$line = trim($line);
if ($line === "") continue;
// ---------------------------------------------------------
// 4A — FORMATO CASSINA A (FIX prezzi concatenati)
// ---------------------------------------------------------
if (preg_match('/^(\d{3}\s+[0-9A-Z]{2,3})\s+(.*)$/', $line, $mA)) {
$codice = trim($mA[1]);
$resto = trim($mA[2]);
// Estrae TUTTI i prezzi concatenati (es. "10,808.9906.460...")
preg_match_all('/\d{1,2}[.,]\d{2,3}/', $resto, $matchesPrezzi);
if (count($matchesPrezzi[0]) >= 2) {
// Descrizione SENZA prezzi
$descr = trim(preg_replace('/\d{1,2}[.,]\d{2,3}/', '', $resto));
// Conversione valori
$vals = array_map(function ($v) {
return floatval(str_replace(",", ".", str_replace(".", "", $v)));
}, $matchesPrezzi[0]);
$items[] = [
"type" => "A",
"codice" => $codice,
"descrizione" => $descr,
"prezzi" => $vals
];
continue;
}
}
// ---------------------------------------------------------
// 4B — FORMATO VECCHIO CASSINA (003 BC cromata … 8 prezzi)
// ---------------------------------------------------------
if (preg_match(
'/^(\d{3}\s+[A-Z]{1,3})\s+([A-Za-zÀ-ù\s]+?)\s+((?:\d{1,2}[.,]\d{2,3}\s*){8,})$/',
$line,
$mB
)) {
$codice = trim($mB[1]);
$descr = trim($mB[2]);
$valuesString = trim($mB[3]);
preg_match_all('/\d{1,2}[.,]\d{2,3}/', $valuesString, $vv);
$vals = array_map(function ($v) {
return floatval(str_replace(",", ".", str_replace(".", "", $v)));
}, $vv[0]);
$categorie = ["Z", "Y", "X", "O", "L", "F/COL", "E/COM", "ALTRO"];
$prezziMappati = [];
foreach ($vals as $i => $v) {
$key = $categorie[$i] ?? ("COL_" . ($i + 1));
$prezziMappati[$key] = $v;
}
$items[] = [
"type" => "B1",
"codice" => $codice,
"descrizione" => $descr,
"prezzi" => $prezziMappati
];
continue;
}
// ---------------------------------------------------------
// 4C — FORMATO LISTINO2 (499 3A 14 5.475 ripetuti)
// ---------------------------------------------------------
$blocks = extractTypeCBlocks($line);
if (!empty($blocks)) {
$desc = $line;
foreach ($blocks as $b) {
$pattern = sprintf(
'/%s\s+%s\s+%s\s+\d{1,2}\.\d{3}/',
$b["codice"],
$b["variante"],
$b["dimensione"]
);
$desc = preg_replace($pattern, "", $desc);
}
$desc = trim($desc);
$items[] = [
"type" => "C",
"descrizione" => $desc,
"varianti" => $blocks
];
continue;
}
}
// ---------------------------------------------------------
// 5) OUTPUT FINALE
// ---------------------------------------------------------
echo json_encode([
"status" => "ok",
"total" => count($items),
"items" => $items
], JSON_PRETTY_PRINT);

View File

@ -0,0 +1,137 @@
<?php
header("Content-Type: application/json; charset=utf-8");
/******************************************************
* CONFIG
******************************************************/
$apiKey = "info@claudiosironi.com_Qfh02D7sAvi2tcx3ZchHpusNaBquCKhJw81fEnkHe2ersQDVOex4IokhCCzaFAz1";
$fileToken = "filetoken://61a780917907f86a340290d22c449357dc68950e9066bd67b2";
// Se passi ?token=xxx usa quello
if (!empty($_GET['token'])) {
$fileToken = $_GET['token'];
}
/******************************************************
* 1) ESTRAGGO CSV (solo pagine con tabelle vere)
******************************************************/
$endpointCsv = "https://api.pdf.co/v1/pdf/convert/to/csv";
$payloadCsv = [
"url" => $fileToken,
"inline" => true,
"detectTables" => true,
"pages" => "all",
"extractColumnBy" => "vertical_lines",
"csvSeparator" => ";"
];
$ch = curl_init($endpointCsv);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"x-api-key: $apiKey"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payloadCsv));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$csvResponse = curl_exec($ch);
curl_close($ch);
$csvJson = json_decode($csvResponse, true);
/******************************************************
* 2) ESTRAGGO ANCHE TESTO (per pagine NON tabellari)
******************************************************/
$endpointText = "https://api.pdf.co/v1/pdf/convert/to/text";
$payloadText = [
"url" => $fileToken,
"inline" => true,
"pages" => "all"
];
$ch = curl_init($endpointText);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"x-api-key: $apiKey"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payloadText));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$textResponse = curl_exec($ch);
curl_close($ch);
$textJson = json_decode($textResponse, true);
/******************************************************
* 3) PARSER CSV TABELLE FORMATO A
******************************************************/
$formatoA = [];
if (isset($csvJson["csv"])) {
$rows = explode("\n", $csvJson["csv"]);
foreach ($rows as $r) {
$cols = str_getcsv($r, ";");
if (count($cols) < 2) continue;
if (!preg_match('/^\d{3}\s+[0-9A-Z]{2,3}$/', trim($cols[0]))) continue;
$formatoA[] = [
"codice" => trim($cols[0]),
"descrizione" => trim($cols[1]),
"prezzi" => array_map(fn($x) => is_numeric(str_replace(",", ".", $x))
? floatval(str_replace(",", ".", $x))
: null, array_slice($cols, 2))
];
}
}
/******************************************************
* 4) PARSER TESTUALE FORMATO B (pagina tipo 499)
******************************************************/
$formatoB = [];
if (isset($textJson["body"])) {
$text = $textJson["body"];
// pattern codice tipo “499 3A 14”
$codeRegex = '/\b(\d{3}\s+[A-Z0-9]{1,2}\s+\d{2})\b/';
// pattern prezzo “5.475” o “5475” o “6.085”
$priceRegex = '/\b\d{1,2}\.?\d{3}\b/';
// Cerca combinazioni CODICE + PREZZO ripetute sulla stessa riga
$linee = explode("\n", $text);
foreach ($linee as $line) {
if (!preg_match_all($codeRegex, $line, $codici)) continue;
if (!preg_match_all($priceRegex, $line, $prezzi)) continue;
$codici = $codici[1];
$prezzi = $prezzi[0];
// Se quantità corrispondono → coppie 1:1
if (count($codici) == count($prezzi)) {
for ($i = 0; $i < count($codici); $i++) {
$formatoB[] = [
"codice" => $codici[$i],
"prezzo" => floatval(str_replace(".", "", $prezzi[$i]))
];
}
}
}
}
/******************************************************
* 5) OUTPUT
******************************************************/
echo json_encode([
"status" => "ok",
"formatoA" => $formatoA,
"formatoB" => $formatoB,
], JSON_PRETTY_PRINT);

View File

@ -45,6 +45,7 @@ $pdo = $db->getConnection();
</head>
<body>
<div class="wrapper">
<?php include('include/navbar.php'); ?>
<div class="dashboard-main-wrapper wrapper">
<?php include('include/topbar.php'); ?>
@ -382,20 +383,30 @@ $pdo = $db->getConnection();
},
success: function(res) {
Swal.close();
let json;
// Se il server ha già restituito un oggetto JSON, usiamolo direttamente
let json = (typeof res === "object") ? res : null;
// Se invece è una stringa JSON, parse
if (!json) {
try {
json = JSON.parse(res);
} catch (e) {
Swal.fire('Errore', res, 'error');
console.error("JSON parse error:", res);
Swal.fire('Errore', 'Risposta non valida dal server.', 'error');
return;
}
}
// Ora siamo sicuri che json è un oggetto valido
if (json.status === 'ok') {
Swal.fire('Successo', `Aggiornati ${json.updated} prezzi.`, 'success');
table.ajax.reload(null, false);
} else {
Swal.fire('Errore', json.message, 'error');
Swal.fire('Errore', json.message || 'Errore sconosciuto.', 'error');
}
},
error: function() {
Swal.fire('Errore', 'Aggiornamento fallito.', 'error');
}
@ -407,6 +418,7 @@ $pdo = $db->getConnection();
});
</script>
</div> <!-- end wrapper -->
</body>
</html>

View File

@ -22,9 +22,10 @@
<ul>
<!-- <li> <a href="index.php"><i class='bx bx-radio-circle'></i>Default</a>
</li> -->
<li> <a href="import_dashboard.php"><i class='bx bx-radio-circle'></i>XLS Import</a>
<li> <a href="import_xls.php"><i class='bx bx-radio-circle'></i>XLS Import</a>
</li>
<li> <a href="import_list.php"><i class='bx bx-radio-circle'></i>Imported LIST</a>
</li>
</ul>
</li>

217
public/userarea/jsonraw.php Normal file
View File

@ -0,0 +1,217 @@
<?php
header("Content-Type: application/json; charset=utf-8");
// ---------------------------------------------------------
// 1) CONFIGURAZIONE
// ---------------------------------------------------------
$apiKey = "info@claudiosironi.com_Qfh02D7sAvi2tcx3ZchHpusNaBquCKhJw81fEnkHe2ersQDVOex4IokhCCzaFAz1";
$fileToken = "filetoken://61a780917907f86a340290d22c449357dc68950e9066bd67b2";
// opzionale: passare un token via GET
if (isset($_GET['token']) && $_GET['token'] !== "") {
$fileToken = $_GET['token'];
}
// ---------------------------------------------------------
// 2) PDF.CO → JSON2 (TUTTE LE PAGINE)
// ---------------------------------------------------------
$endpoint = "https://api.pdf.co/v1/pdf/convert/to/json2";
$payload = [
"url" => $fileToken,
"inline" => true,
"detectTables" => true,
"pages" => "all"
];
$ch = curl_init($endpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"x-api-key: $apiKey"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if (!$response) {
echo json_encode(["error" => "Errore CURL: " . curl_error($ch)]);
exit;
}
curl_close($ch);
$json = json_decode($response, true);
// ---------------------------------------------------------
// 3) VALIDAZIONE
// ---------------------------------------------------------
if (!isset($json["body"]["document"]["page"])) {
echo json_encode([
"error" => true,
"message" => "PDF.co JSON senza pagine valide",
"raw" => $json
]);
exit;
}
$pages = $json["body"]["document"]["page"];
// ---------------------------------------------------------
// 4) FUNZIONI UTILI
// ---------------------------------------------------------
// Formato A 291 02F
function isCodeTypeA($txt)
{
return preg_match('/^\d{3}\s+[0-9A-Z]{2,3}$/', $txt);
}
// Formato C blocchi ripetuti (499 3A 14 5.475)
function extractTypeCBlocks($line)
{
preg_match_all(
'/(\d{3})\s+([0-9A-Z]{1,3})\s+(\d{2})\s+(\d{1,3}\.\d{3})/',
$line,
$m,
PREG_SET_ORDER
);
$out = [];
foreach ($m as $b) {
$out[] = [
"codice" => $b[1],
"variante" => $b[2],
"dimensione" => $b[3],
"prezzo" => floatval(str_replace(".", "", $b[4]))
];
}
return $out;
}
// ---------------------------------------------------------
// 5) PARSER PER UNA SINGOLA RIGA (ricostruita)
// ---------------------------------------------------------
function parseLine($line)
{
// FORMATO A
if (preg_match('/^(\d{3}\s+[0-9A-Z]{2,3})\s+(.*)$/', $line, $mA)) {
$codice = trim($mA[1]);
$resto = trim($mA[2]);
preg_match_all('/\d{1,3}[.,]\d{2,3}/', $resto, $matchesPrezzi);
if (count($matchesPrezzi[0]) >= 2) {
$descr = trim(preg_replace('/\d{1,3}[.,]\d{2,3}/', '', $resto));
$vals = array_map(function ($v) {
return floatval(str_replace(",", ".", str_replace(".", "", $v)));
}, $matchesPrezzi[0]);
return [
"type" => "A",
"codice" => $codice,
"descrizione" => $descr,
"prezzi" => $vals
];
}
}
// FORMATO B1
if (preg_match(
'/^(\d{3}\s+[A-Z]{1,3})\s+([A-Za-zÀ-ù0-9\s]+?)\s+((?:\d{1,3}[.,]\d{2,3}\s*){4,})$/',
$line,
$mB
)) {
$codice = trim($mB[1]);
$descr = trim($mB[2]);
$valuesString = trim($mB[3]);
preg_match_all('/\d{1,3}[.,]\d{2,3}/', $valuesString, $vv);
$vals = array_map(function ($v) {
return floatval(str_replace(",", ".", str_replace(".", "", $v)));
}, $vv[0]);
return [
"type" => "B1",
"codice" => $codice,
"descrizione" => $descr,
"prezzi" => $vals
];
}
// FORMATO C (ripetuto in riga)
$blocks = extractTypeCBlocks($line);
if (!empty($blocks)) {
$desc = $line;
foreach ($blocks as $b) {
$pattern = sprintf(
'/%s\s+%s\s+%s\s+\d{1,3}\.\d{3}/',
$b["codice"],
$b["variante"],
$b["dimensione"]
);
$desc = preg_replace($pattern, "", $desc);
}
$desc = trim($desc);
return [
"type" => "C",
"descrizione" => $desc,
"varianti" => $blocks
];
}
// Nessun match
return null;
}
// ---------------------------------------------------------
// 6) PROCESSAMENTO DI TUTTE LE PAGINE
// ---------------------------------------------------------
$items = [];
foreach ($pages as $p) {
if (!isset($p["row"])) continue;
// Ricostruisco tutte le vere righe (“flat lines”)
$flatLines = [];
foreach ($p["row"] as $row) {
$line = "";
foreach ($row["column"] as $col) {
if (!empty($col["text"]["text"])) {
$line .= " " . trim($col["text"]["text"]);
}
}
$line = trim($line);
if ($line !== "") {
$flatLines[] = $line;
}
}
// Applico i parser su ogni riga ricostruita
foreach ($flatLines as $l) {
$parsed = parseLine($l);
if ($parsed !== null) {
$items[] = $parsed;
}
}
}
// ---------------------------------------------------------
// 7) OUTPUT FINALE
// ---------------------------------------------------------
echo json_encode([
"status" => "ok",
"total" => count($items),
"items" => $items
], JSON_PRETTY_PRINT);

BIN
public/userarea/listino.pdf Normal file

Binary file not shown.

View File

@ -6660,6 +6660,10 @@ return array(
'Spatie\\LaravelPackageTools\\Exceptions\\InvalidPackage' => $vendorDir . '/spatie/laravel-package-tools/src/Exceptions/InvalidPackage.php',
'Spatie\\LaravelPackageTools\\Package' => $vendorDir . '/spatie/laravel-package-tools/src/Package.php',
'Spatie\\LaravelPackageTools\\PackageServiceProvider' => $vendorDir . '/spatie/laravel-package-tools/src/PackageServiceProvider.php',
'Spatie\\PdfToText\\Exceptions\\BinaryNotFoundException' => $vendorDir . '/spatie/pdf-to-text/src/Exceptions/BinaryNotFoundException.php',
'Spatie\\PdfToText\\Exceptions\\CouldNotExtractText' => $vendorDir . '/spatie/pdf-to-text/src/Exceptions/CouldNotExtractText.php',
'Spatie\\PdfToText\\Exceptions\\PdfNotFound' => $vendorDir . '/spatie/pdf-to-text/src/Exceptions/PdfNotFound.php',
'Spatie\\PdfToText\\Pdf' => $vendorDir . '/spatie/pdf-to-text/src/Pdf.php',
'Spatie\\QueryBuilder\\AllowedFilter' => $vendorDir . '/spatie/laravel-query-builder/src/AllowedFilter.php',
'Spatie\\QueryBuilder\\AllowedInclude' => $vendorDir . '/spatie/laravel-query-builder/src/AllowedInclude.php',
'Spatie\\QueryBuilder\\AllowedSort' => $vendorDir . '/spatie/laravel-query-builder/src/AllowedSort.php',

View File

@ -54,6 +54,7 @@ return array(
'Symfony\\Component\\Clock\\' => array($vendorDir . '/symfony/clock'),
'Spatie\\QueryBuilder\\Database\\Factories\\' => array($vendorDir . '/spatie/laravel-query-builder/database/factories'),
'Spatie\\QueryBuilder\\' => array($vendorDir . '/spatie/laravel-query-builder/src'),
'Spatie\\PdfToText\\' => array($vendorDir . '/spatie/pdf-to-text/src'),
'Spatie\\LaravelPackageTools\\' => array($vendorDir . '/spatie/laravel-package-tools/src'),
'Spatie\\LaravelIgnition\\' => array($vendorDir . '/spatie/laravel-ignition/src', $vendorDir . '/spatie/error-solutions/legacy/laravel-ignition'),
'Spatie\\Ignition\\' => array($vendorDir . '/spatie/ignition/src', $vendorDir . '/spatie/error-solutions/legacy/ignition'),

View File

@ -114,6 +114,7 @@ class ComposerStaticInitc91cd9c5b1e6a9e8573a14b799ea9342
'Symfony\\Component\\Clock\\' => 24,
'Spatie\\QueryBuilder\\Database\\Factories\\' => 39,
'Spatie\\QueryBuilder\\' => 20,
'Spatie\\PdfToText\\' => 17,
'Spatie\\LaravelPackageTools\\' => 27,
'Spatie\\LaravelIgnition\\' => 23,
'Spatie\\Ignition\\' => 16,
@ -440,6 +441,10 @@ class ComposerStaticInitc91cd9c5b1e6a9e8573a14b799ea9342
array (
0 => __DIR__ . '/..' . '/spatie/laravel-query-builder/src',
),
'Spatie\\PdfToText\\' =>
array (
0 => __DIR__ . '/..' . '/spatie/pdf-to-text/src',
),
'Spatie\\LaravelPackageTools\\' =>
array (
0 => __DIR__ . '/..' . '/spatie/laravel-package-tools/src',
@ -7483,6 +7488,10 @@ class ComposerStaticInitc91cd9c5b1e6a9e8573a14b799ea9342
'Spatie\\LaravelPackageTools\\Exceptions\\InvalidPackage' => __DIR__ . '/..' . '/spatie/laravel-package-tools/src/Exceptions/InvalidPackage.php',
'Spatie\\LaravelPackageTools\\Package' => __DIR__ . '/..' . '/spatie/laravel-package-tools/src/Package.php',
'Spatie\\LaravelPackageTools\\PackageServiceProvider' => __DIR__ . '/..' . '/spatie/laravel-package-tools/src/PackageServiceProvider.php',
'Spatie\\PdfToText\\Exceptions\\BinaryNotFoundException' => __DIR__ . '/..' . '/spatie/pdf-to-text/src/Exceptions/BinaryNotFoundException.php',
'Spatie\\PdfToText\\Exceptions\\CouldNotExtractText' => __DIR__ . '/..' . '/spatie/pdf-to-text/src/Exceptions/CouldNotExtractText.php',
'Spatie\\PdfToText\\Exceptions\\PdfNotFound' => __DIR__ . '/..' . '/spatie/pdf-to-text/src/Exceptions/PdfNotFound.php',
'Spatie\\PdfToText\\Pdf' => __DIR__ . '/..' . '/spatie/pdf-to-text/src/Pdf.php',
'Spatie\\QueryBuilder\\AllowedFilter' => __DIR__ . '/..' . '/spatie/laravel-query-builder/src/AllowedFilter.php',
'Spatie\\QueryBuilder\\AllowedInclude' => __DIR__ . '/..' . '/spatie/laravel-query-builder/src/AllowedInclude.php',
'Spatie\\QueryBuilder\\AllowedSort' => __DIR__ . '/..' . '/spatie/laravel-query-builder/src/AllowedSort.php',

View File

@ -8827,6 +8827,67 @@
],
"install-path": "../spatie/laravel-query-builder"
},
{
"name": "spatie/pdf-to-text",
"version": "1.54.1",
"version_normalized": "1.54.1.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/pdf-to-text.git",
"reference": "ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/pdf-to-text/zipball/ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb",
"reference": "ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb",
"shasum": ""
},
"require": {
"php": "^7.4|^8.0",
"symfony/process": "^4.0|^5.0|^6.0|^7.0"
},
"require-dev": {
"pestphp/pest-plugin-laravel": "^1.3",
"phpunit/phpunit": "^9.5"
},
"time": "2025-06-13T15:23:19+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Spatie\\PdfToText\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Freek Van der Herten",
"email": "freek@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
}
],
"description": "Extract text from a pdf",
"homepage": "https://github.com/spatie/pdf-to-text",
"keywords": [
"pdf-to-text",
"spatie"
],
"support": {
"issues": "https://github.com/spatie/pdf-to-text/issues",
"source": "https://github.com/spatie/pdf-to-text/tree/1.54.1"
},
"funding": [
{
"url": "https://spatie.be/open-source/support-us",
"type": "custom"
}
],
"install-path": "../spatie/pdf-to-text"
},
{
"name": "symfony/clock",
"version": "v7.1.1",

View File

@ -3,7 +3,7 @@
'name' => 'loshmis/vanguard',
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => 'e75be99e43b28088315b19f86eee2e6869c7c844',
'reference' => '6b65b31932e62bc55f5c539e7856ca8eb8440782',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -688,7 +688,7 @@
'loshmis/vanguard' => array(
'pretty_version' => 'dev-main',
'version' => 'dev-main',
'reference' => 'e75be99e43b28088315b19f86eee2e6869c7c844',
'reference' => '6b65b31932e62bc55f5c539e7856ca8eb8440782',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -1391,6 +1391,15 @@
0 => '*',
),
),
'spatie/pdf-to-text' => array(
'pretty_version' => '1.54.1',
'version' => '1.54.1.0',
'reference' => 'ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb',
'type' => 'library',
'install_path' => __DIR__ . '/../spatie/pdf-to-text',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/clock' => array(
'pretty_version' => 'v7.1.1',
'version' => '7.1.1.0',