From 1804605cad81baeb3069d142e5a006a7374b7928 Mon Sep 17 00:00:00 2001 From: solocla Date: Mon, 17 Nov 2025 15:05:10 +0100 Subject: [PATCH] extrac prices pdfco --- .../Controllers/Web/Auth/LoginController.php | 4 +- composer.json | 1 + composer.lock | 60 +- public/assets/img/logo.png | Bin 10636 -> 6132 bytes public/userarea/extract_prices.php | 73 ++ public/userarea/extract_prices_pdfco.php | 218 ++++++ public/userarea/extract_prices_table.php | 137 ++++ public/userarea/import_list.php | 658 +++++++++--------- public/userarea/include/navbar.php | 5 +- public/userarea/jsonraw.php | 217 ++++++ public/userarea/listino.pdf | Bin 0 -> 29823 bytes vendor/composer/autoload_classmap.php | 4 + vendor/composer/autoload_psr4.php | 1 + vendor/composer/autoload_static.php | 9 + vendor/composer/installed.json | 61 ++ vendor/composer/installed.php | 13 +- 16 files changed, 1131 insertions(+), 330 deletions(-) create mode 100644 public/userarea/extract_prices.php create mode 100644 public/userarea/extract_prices_pdfco.php create mode 100644 public/userarea/extract_prices_table.php create mode 100644 public/userarea/jsonraw.php create mode 100644 public/userarea/listino.pdf diff --git a/app/Http/Controllers/Web/Auth/LoginController.php b/app/Http/Controllers/Web/Auth/LoginController.php index 69d8716..a1e86e4 100644 --- a/app/Http/Controllers/Web/Auth/LoginController.php +++ b/app/Http/Controllers/Web/Auth/LoginController.php @@ -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 diff --git a/composer.json b/composer.json index 7c6f34f..6c53bc5 100644 --- a/composer.json +++ b/composer.json @@ -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", diff --git a/composer.lock b/composer.lock index 8ad8c93..7996ab1 100644 --- a/composer.lock +++ b/composer.lock @@ -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", diff --git a/public/assets/img/logo.png b/public/assets/img/logo.png index a8568b8b873f0d5d385a409e07014b5d5f77afb2..076c4b7c6fec91a3cfbd9ee0da629bea7cbf7769 100644 GIT binary patch literal 6132 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 X*V*iGi0B@W)Po=z2I@%Fmr?%*zZ4xL literal 10636 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 Hu?+hU=p$k@ diff --git a/public/userarea/extract_prices.php b/public/userarea/extract_prices.php new file mode 100644 index 0000000..f5d75b4 --- /dev/null +++ b/public/userarea/extract_prices.php @@ -0,0 +1,73 @@ + "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); diff --git a/public/userarea/extract_prices_pdfco.php b/public/userarea/extract_prices_pdfco.php new file mode 100644 index 0000000..2285f5f --- /dev/null +++ b/public/userarea/extract_prices_pdfco.php @@ -0,0 +1,218 @@ + $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); diff --git a/public/userarea/extract_prices_table.php b/public/userarea/extract_prices_table.php new file mode 100644 index 0000000..b68b55b --- /dev/null +++ b/public/userarea/extract_prices_table.php @@ -0,0 +1,137 @@ + $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); diff --git a/public/userarea/import_list.php b/public/userarea/import_list.php index 8b3b4e6..4af6b12 100644 --- a/public/userarea/import_list.php +++ b/public/userarea/import_list.php @@ -45,139 +45,140 @@ $pdo = $db->getConnection(); - -
- +
+ +
+ -
-
-
-
-

Imported Data

-
- - +
+
+
+
+

Imported Data

+
+ + +
-
-
-
- +
+
+ +
-
-
- +
+
- - - - - - - - - - - - - - - - - - -
IDCollectionCategoryModelModel DescriptionMod.CodeDescriptionFinish.CodeFinishing DescriptionAvailable QtyWHPriceActions
+ + + + ID + Collection + Category + Model + Model Description + Mod.Code + Description + Finish.Code + Finishing Description + Available Qty + WH + Price + Actions + + + +
+ +
- -
+ + + - - - - - + +
\ No newline at end of file diff --git a/public/userarea/include/navbar.php b/public/userarea/include/navbar.php index 5df1b53..932a558 100644 --- a/public/userarea/include/navbar.php +++ b/public/userarea/include/navbar.php @@ -22,9 +22,10 @@ diff --git a/public/userarea/jsonraw.php b/public/userarea/jsonraw.php new file mode 100644 index 0000000..24b67b4 --- /dev/null +++ b/public/userarea/jsonraw.php @@ -0,0 +1,217 @@ + $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); diff --git a/public/userarea/listino.pdf b/public/userarea/listino.pdf new file mode 100644 index 0000000000000000000000000000000000000000..676085973c3e1607a49be72f079fd8389716473d GIT binary patch literal 29823 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 $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', diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 89947f5..7b49a89 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -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'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 6302cef..8ed4841 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -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', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 97a9efe..2e77d0d 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -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", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 5ad65f2..94a741a 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -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',