]> _ Git - fluidbook-toolbox.git/commitdiff
wait #7697 @7
authorVincent Vanwaelscappel <vincent@cubedesigners.com>
Tue, 9 Sep 2025 13:51:06 +0000 (15:51 +0200)
committerVincent Vanwaelscappel <vincent@cubedesigners.com>
Tue, 9 Sep 2025 13:51:06 +0000 (15:51 +0200)
app/Http/Controllers/Admin/CrudController.php
app/Http/Controllers/Admin/FluidbookExternalInstallServerCrudController.php
app/Http/Controllers/Admin/FluidbookPublicationCrudController.php
app/Http/Controllers/Admin/Operations/FluidbookCollection/SettingsExportOperation.php
app/Jobs/FluidbookCollectionRefreshIndex.php [new file with mode: 0644]
app/Models/FluidbookCollection.php
app/Models/FluidbookPublication.php
composer.json
composer.lock

index ccc8f6c7fe468749d6ab46598afb7b5be84f2f1d..1a559260143eede78754789cc68140b047b546e6 100644 (file)
@@ -7,18 +7,15 @@ class CrudController extends \Cubist\Backpack\Magic\Controllers\CubistMagicContr
     use \Cubist\Backpack\Magic\Operations\CreateOperation;
        use \Cubist\Backpack\Http\Controllers\Operations\CloneEditOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
-       use \Cubist\Backpack\Http\Controllers\Operations\BulkPublishOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\CloneOperation;
-       use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
-       use \Backpack\CRUD\app\Http\Controllers\Operations\BulkDeleteOperation;
        
 
 
     /*
        */
 
-    protected $_modelNamespace = 'App\Models\Base\ToolboxHRModel';
+    protected $_modelNamespace = 'App\Models\Badges\Base';
     protected $_routeURL = '';
     protected $_singular = '';
     protected $_plural = '';
index c7e04d7d3fdba866dd826c37fbd47e43f5061749..eb062ec6e2dc8083a76007b7dc9245b1323ea13e 100644 (file)
@@ -13,6 +13,7 @@ class FluidbookExternalInstallServerCrudController extends \Cubist\Backpack\Magi
        use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
        use \Backpack\CRUD\app\Http\Controllers\Operations\BulkDeleteOperation;
        use \App\Http\Controllers\Admin\Operations\ServerOperation;
+       use \App\Http\Controllers\Admin\Operations\ChangeownerOperation;
        
 
 
index 53ccafe7fc0970dc146df1d02dda7513eb4bc5b1..0a2987544f7fa85385f7d352d0b9aa484f16046d 100644 (file)
@@ -15,16 +15,18 @@ class FluidbookPublicationCrudController extends \Cubist\Backpack\Magic\Controll
        use \App\Http\Controllers\Admin\Operations\FluidbookPublication\CloneOperation;
        use \App\Http\Controllers\Admin\Operations\FluidbookPublication\DeletefbOperation;
        use \App\Http\Controllers\Admin\Operations\FluidbookPublication\EditOperation;
-    use \App\Http\Controllers\Admin\Operations\FluidbookPublication\MarkdownOperation;
-    use \App\Http\Controllers\Admin\Operations\ChangeownerOperation;
-    use \App\Http\Controllers\Admin\Operations\ChangestatusOperation;
-    use \App\Http\Controllers\Admin\Operations\InvoiceOperation;
-    use \App\Http\Controllers\Admin\Operations\FluidbookPublication\SettingsExportOperation;
-    use \App\Http\Controllers\Admin\Operations\FluidbookPublication\Services\SocialImageOperation;
-    use \App\Http\Controllers\Admin\Operations\FluidbookPublication\Services\ExportPdfOperation;
-    use \App\Http\Controllers\Admin\Operations\FluidbookPublication\Services\GetPageFromWebsiteOperation;
-    use \App\Http\Controllers\Admin\Operations\FluidbookPublication\Services\BastideOperation;
-
+       use \App\Http\Controllers\Admin\Operations\ChangeownerOperation;
+       use \App\Http\Controllers\Admin\Operations\ChangestatusOperation;
+       use \App\Http\Controllers\Admin\Operations\InvoiceOperation;
+       use \App\Http\Controllers\Admin\Operations\FluidbookPublication\SettingsExportOperation;
+       use \App\Http\Controllers\Admin\Operations\FluidbookPublication\MarkdownOperation;
+       use \App\Http\Controllers\Admin\Operations\FluidbookPublication\Services\SocialImageOperation;
+       use \App\Http\Controllers\Admin\Operations\FluidbookPublication\Services\ExportPdfOperation;
+       use \App\Http\Controllers\Admin\Operations\FluidbookPublication\Services\GetPageFromWebsiteOperation;
+       use \App\Http\Controllers\Admin\Operations\FluidbookPublication\Services\FormOperation;
+       use \App\Http\Controllers\Admin\Operations\FluidbookPublication\Services\BastideOperation;
+       use \App\Http\Controllers\Admin\Operations\FluidbookPublication\Services\PumaOperation;
+       
 
 
     /*
index 45eff15d0f3c51701d697aca3c1714a1fb983119..be763a1b65b8d75115ae3441c2dc5012d3f887a8 100644 (file)
@@ -17,7 +17,6 @@ trait SettingsExportOperation
     protected function setupSettingsRoutes($segment, $routeName, $controller)
     {
         Route::match(['get', 'post'], $segment . '/{id}/download_settings', $controller . '@collectionSettings')->name("download_settings_by_ids");
-        Route::match(['post'], $segment . '/search', $controller . '@search');
     }
 
     protected function collectionSettings($id)
@@ -37,70 +36,4 @@ trait SettingsExportOperation
 
         return response()->download($file, 'settings_export.xlsx')->deleteFileAfterSend();
     }
-
-    protected function connectToSearchServer($id) {
-        $apiKey = FluidbookCollection::where('id', $id)->get('api_key')->toArray()[0]['api_key'];
-        $host = FluidbookCollection::where('id', $id)->get('server_search_host')->toArray()[0]['server_search_host'];
-
-        return new Client(
-            [
-                'api_key'         => $apiKey,
-                'nodes'           => [
-                    [
-                        'host'     => $host, // For Typesense Cloud use xxx.a1.typesense.net
-                        'port'     => '',// For Typesense Cloud use 443
-                        'protocol' => 'https',// For Typesense Cloud use https
-                    ],
-                ],
-                'connection_timeout_seconds' => 3600,
-            ]
-        );
-    }
-
-    protected function indexContent($publications, $id) {
-        $client = $this->connectToSearchServer($id);
-
-        $texts = [];
-        $content = '';
-
-        foreach ($publications as $publication) {
-            $book_id = $publication['fluidbook'];
-            $fb = FluidbookPublication::find($book_id);
-            $pages = $fb->getPagesNumber();
-            $ref = $fb->reference;
-
-            for($i = 1; $i <= $pages; $i++) {
-                $getContent = file_get_contents($fb->getTextFile($i));
-                if(in_array('gz', explode('.', $fb->getTextFile($i)))) {
-                    $content .= gzdecode($getContent);
-                }else {
-                    $content .= $getContent;
-                }
-                $content .= ' ';
-            }
-
-            $texts[$book_id] = [
-                "text" => $content,
-                "id" => $book_id,
-                "reference" => $ref ?? '-'
-            ];
-            $content = '';
-        }
-
-        $booksSchema = [
-            "name" => "fluidbooks",
-            "fields" => [
-                ["name"=> ".*", "type"=> "auto"]
-            ]
-        ];
-
-        $client->collections['fluidbooks']->delete();
-
-        $client->collections->create($booksSchema);
-        $this->addContent($client, $texts);
-    }
-
-    protected function addContent($client, $content) {
-        $client->collections["fluidbooks"]->documents->import($content, ['action' => 'create']);
-    }
 }
diff --git a/app/Jobs/FluidbookCollectionRefreshIndex.php b/app/Jobs/FluidbookCollectionRefreshIndex.php
new file mode 100644 (file)
index 0000000..b0042b9
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Models\FluidbookCollection;
+
+class FluidbookCollectionRefreshIndex extends Base
+{
+    protected $collection;
+
+    public function __construct($collection)
+    {
+        parent::__construct();
+        $this->collection = $collection;
+    }
+
+    public function handle()
+    {
+        if (!($this->collection instanceof FluidbookCollection)) {
+            $this->collection = FluidbookCollection::withoutGlobalScopes()->find($this->collection);
+        }
+        $this->collection->refreshIndex();
+    }
+}
index e26830196acac563c46b5ae2e1aabdf201441fe7..a775b61b0db1532fa5f41cdebc7d688c59209fdd 100644 (file)
@@ -9,6 +9,7 @@ use App\Http\Controllers\Admin\Operations\ChangestatusOperation;
 use App\Http\Controllers\Admin\Operations\FluidbookCollection\DownloadOperation;
 use App\Http\Controllers\Admin\Operations\FluidbookCollection\PreviewOperation;
 use App\Http\Controllers\Admin\Operations\FluidbookCollection\SettingsExportOperation;
+use App\Jobs\FluidbookCollectionRefreshIndex;
 use App\Models\Base\ToolboxDownloadable;
 use App\Jobs\RefreshUsersTree;
 use App\Models\Base\ToolboxStatusModel;
@@ -20,14 +21,20 @@ use Cubist\Backpack\Magic\Fields\BunchOfFieldsMultiple;
 use Cubist\Backpack\Magic\Fields\Checkbox;
 use Cubist\Backpack\Magic\Fields\ExternalPath;
 use Cubist\Backpack\Magic\Fields\FilesOrURL;
+use Cubist\Backpack\Magic\Fields\FormSeparator;
 use Cubist\Backpack\Magic\Fields\Hidden;
 use Cubist\Backpack\Magic\Fields\Integer;
 use Cubist\Backpack\Magic\Fields\SelectFromArray;
 use Cubist\Backpack\Magic\Fields\Text;
 use Cubist\Util\Files\Files;
+use Cubist\Util\Gzip;
+use Http\Client\Exception;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Http\UploadedFile;
 use Illuminate\Support\Facades\Auth;
+use Typesense\Client;
+use Typesense\Exceptions\ConfigError;
+use Typesense\Exceptions\TypesenseClientError;
 
 // __('!! Collections de fluidbooks')
 class FluidbookCollection extends ToolboxStatusModel
@@ -81,14 +88,17 @@ class FluidbookCollection extends ToolboxStatusModel
         $this->addField('version', FluidbookExportVersion::class, __('Version'), ['when' => ['type' => 'export']]);
         $excluded = array_diff(array_keys(FluidbookExportVersion::getVersions()), ['online', 'sharepoint']);
         $this->addField('version_multilang', FluidbookExportVersion::class, __('Version'), ['when' => ['type' => 'export_multilang'], 'excluded_options' => $excluded, 'default' => 'online']);
-        $this->addField('publications', BunchOfFieldsMultiple::class, __('Publications'), ['bunch' => CollectionPublication::class, 'edit_label' => '%fluidbook > %dir']);
+
         $this->addField('install', ExternalPath::class, 'Installer sur un serveur externe', ['default' => '', 'fake' => true, 'translatable' => false, 'store_in' => 'settings', 'servers_model' => FluidbookExternalInstallServer::class, ['when' => ['type' => ['export', 'export_multilang']]]]);
         $this->addField('override_settings', BunchOfFieldsMultiple::class, __('Redéfinir les paramètres lors de l\'export'), ['bunch' => Fluidbook_Setting::class]);
         $this->addField('linksAssets', FilesOrURL::class, __('Charger ou remplacer des assets sur tous les fluidbooks de la collection'), ['hint' => __('Cela écrasera les fichiers sur tous les fluidbooks de la collection si ils portent le même nom d\'un asset chargé ici')]);
         $this->addField('visits_counter', Integer::class, 'Compteur de visites', ['can' => 'fluidbook-collection:write', 'read_only' => true, 'default' => 0, 'column' => true, 'column_label' => '<i class="las la-chart-area" title="' . __('Compteur de visites du lien de préview') . '"></i>', 'searchLogic' => false]);
-        $this->addField('type_index', Text::class, __('Type d\'index'));
-        $this->addField('server_search_host', Text::class, __('Hôte du serveur de recherche'));
-        $this->addField('api_key', Text::class, __('Clé API'));
+        $this->addField('sep_search', FormSeparator::class);
+        $this->addField('search', SelectFromArray::class, __('Indexer les contenus dans un moteur de recherche'), ['options' => ['none' => __('Non'), 'typesense' => __('Serveur typesense')]]);
+        $this->addField('search_host', Text::class, __('Hôte'), ['when' => ['search' => 'typesense']]);
+        $this->addField('search_key', Text::class, __('Clé API'), ['when' => ['search' => 'typesense']]);
+        $this->addField('sep_pubs', FormSeparator::class);
+        $this->addField('publications', BunchOfFieldsMultiple::class, __('Publications'), ['bunch' => CollectionPublication::class, 'edit_label' => '%fluidbook > %dir']);
     }
 
 
@@ -178,4 +188,77 @@ class FluidbookCollection extends ToolboxStatusModel
 
         RefreshUsersTree::dispatchSync();
     }
+
+    /**
+     * @throws ConfigError
+     */
+    protected function _connectToSearchServer(): Client
+    {
+        $apiKey = $this->search_key;
+        $host = $this->search_host;
+
+        return new Client(
+            [
+                'api_key' => $apiKey,
+                'nodes' => [
+                    [
+                        'host' => $host, // For Typesense Cloud use xxx.a1.typesense.net
+                        'port' => '',// For Typesense Cloud use 443
+                        'protocol' => 'https',// For Typesense Cloud use https
+                    ],
+                ],
+                'connection_timeout_seconds' => 3600,
+            ]
+        );
+    }
+
+    /**
+     * @throws Exception
+     * @throws TypesenseClientError
+     * @throws ConfigError
+     * @throws \JsonException
+     */
+    public function refreshIndex()
+    {
+        if (!$this->search === 'none') {
+            dddd(':/');
+            return;
+        }
+
+
+        $texts = [];
+        foreach ($this->publications as $publication) {
+            $book_id = $publication['fluidbook'];
+            /** @var FluidbookPublication $fb */
+            $fb = FluidbookPublication::withoutGlobalScopes()->find($book_id);
+            if (null === $fb) {
+                continue;
+            }
+
+            $texts[$book_id] = [
+                "text" => $fb->getFullText(),
+                "id" => $book_id,
+                "reference" => $fb->reference ?? '-'
+            ];
+        }
+
+        $booksSchema = [
+            "name" => "fluidbooks",
+            "fields" => [
+                ["name" => ".*", "type" => "auto"]
+            ]
+        ];
+        
+        $client = $this->_connectToSearchServer();
+        $client->collections['fluidbooks']->delete();
+        $client->collections->create($booksSchema);
+        $client->collections["fluidbooks"]->documents->import($texts, ['action' => 'create']);
+    }
+
+    public function onSaved(): bool
+    {
+        $res = parent::onSaved();
+        dispatch(new FluidbookCollectionRefreshIndex($this->id));
+        return $res;
+    }
 }
index a9637bd55a30acf206a545de56c4d8e02de56299..25f4b2b9c126f82bb96432fba66672f6baacf56f 100644 (file)
@@ -65,6 +65,7 @@ use Cubist\Util\ArrayUtil;
 use Cubist\Util\CommandLine\Rsync;
 use Cubist\Util\Files\Files;
 use Cubist\Util\Graphics\Image;
+use Cubist\Util\Gzip;
 use Cubist\Util\Json;
 use Cubist\Util\Str;
 use Datetime;
@@ -481,7 +482,7 @@ class FluidbookPublication extends ToolboxStatusModel
                 foreach ($this->getComposition() as $page => $d) {
                     try {
                         $json['pages'][$page] = file_get_contents($this->getAccessibleFile($page));
-                    }catch (\Exception $e) {
+                    } catch (\Exception $e) {
                         dump($page, $e->getMessage());
                     }
                 }
@@ -651,6 +652,34 @@ class FluidbookPublication extends ToolboxStatusModel
         return ($this->transparentPage ? 'png' : $this->imageFormat) ?: 'jpg';
     }
 
+    public function getFullText()
+    {
+        $cacheFile = Files::mkdir($this->protected_path('fluidbookpublication/cache/fulltext/')) . $this->id . '.txt';
+        $pages = $this->getPagesNumber();
+        $refresh = false;
+        if (!Gzip::file_exists($cacheFile) || ($cacheFileMtime = Gzip::filemtime($cacheFile)) < $this->getCompositionUpdate()) {
+            $refresh = true;
+        }
+        if (!$refresh) {
+            for ($i = 1; $i <= $pages; $i++) {
+                if (Gzip::filemtime($this->getTextFile($i)) > $cacheFileMtime) {
+                    $refresh = true;
+                    break;
+                }
+            }
+        }
+
+        if (!$refresh) {
+            return Gzip::file_get_contents($cacheFile);
+        }
+        $res = '';
+        for ($i = 1; $i <= $pages; $i++) {
+            $res .= Gzip::file_get_contents($this->getTextFile($i));
+        }
+        Gzip::file_put_contents($cacheFile, $res);
+        return $res;
+    }
+
     public function protected_path($path, $forceRegion = null)
     {
         $r = $forceRegion ?? $this->region;
index 719345b16e2643ad7158d1419a97578c8a5adfd5..8144b0998baedb630aa426bb1cafc7dcf752bed3 100644 (file)
@@ -70,6 +70,7 @@
         "simplesoftwareio/simple-qrcode": "^4.2",
         "symfony/http-client": "^v6.4.0",
         "theafolayan/listmonk-laravel": "^1.3",
+        "typesense/typesense-php": "^5.1",
         "voku/simple_html_dom": "^4.8"
     },
     "require-dev": {
index 1c1a145b3db6ca7aeade502d81b950a5310eec8f..9da6d518a0028119d5b37aa7a372e4882768948b 100644 (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": "0f3f27cdcd5953aa6c227e51d5c5b3b4",
+    "content-hash": "c0ba0973d873ef25b9b2aa81b60bc007",
     "packages": [
         {
             "name": "archtechx/enums",
         },
         {
             "name": "doctrine/dbal",
-            "version": "3.10.1",
+            "version": "3.10.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/doctrine/dbal.git",
-                "reference": "3626601014388095d3af9de7e9e958623b7ef005"
+                "reference": "c6c16cf787eaba3112203dfcd715fa2059c62282"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/dbal/zipball/3626601014388095d3af9de7e9e958623b7ef005",
-                "reference": "3626601014388095d3af9de7e9e958623b7ef005",
+                "url": "https://api.github.com/repos/doctrine/dbal/zipball/c6c16cf787eaba3112203dfcd715fa2059c62282",
+                "reference": "c6c16cf787eaba3112203dfcd715fa2059c62282",
                 "shasum": ""
             },
             "require": {
             },
             "require-dev": {
                 "doctrine/cache": "^1.11|^2.0",
-                "doctrine/coding-standard": "13.0.0",
+                "doctrine/coding-standard": "13.0.1",
                 "fig/log-test": "^1",
                 "jetbrains/phpstorm-stubs": "2023.1",
-                "phpstan/phpstan": "2.1.17",
+                "phpstan/phpstan": "2.1.22",
                 "phpstan/phpstan-strict-rules": "^2",
                 "phpunit/phpunit": "9.6.23",
                 "slevomat/coding-standard": "8.16.2",
             ],
             "support": {
                 "issues": "https://github.com/doctrine/dbal/issues",
-                "source": "https://github.com/doctrine/dbal/tree/3.10.1"
+                "source": "https://github.com/doctrine/dbal/tree/3.10.2"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-08-05T12:18:06+00:00"
+            "time": "2025-09-04T23:51:27+00:00"
         },
         {
             "name": "doctrine/deprecations",
         },
         {
             "name": "ramsey/uuid",
-            "version": "4.9.0",
+            "version": "4.9.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/ramsey/uuid.git",
-                "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0"
+                "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0",
-                "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0",
+                "url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+                "reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
                 "shasum": ""
             },
             "require": {
-                "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13",
+                "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
                 "php": "^8.0",
                 "ramsey/collection": "^1.2 || ^2.0"
             },
             ],
             "support": {
                 "issues": "https://github.com/ramsey/uuid/issues",
-                "source": "https://github.com/ramsey/uuid/tree/4.9.0"
+                "source": "https://github.com/ramsey/uuid/tree/4.9.1"
             },
-            "time": "2025-06-25T14:20:11+00:00"
+            "time": "2025-09-04T20:59:21+00:00"
         },
         {
             "name": "react/promise",
         },
         {
             "name": "symfony/console",
-            "version": "v6.4.24",
+            "version": "v6.4.25",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git",
-                "reference": "59266a5bf6a596e3e0844fd95e6ad7ea3c1d3350"
+                "reference": "273fd29ff30ba0a88ca5fb83f7cf1ab69306adae"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/59266a5bf6a596e3e0844fd95e6ad7ea3c1d3350",
-                "reference": "59266a5bf6a596e3e0844fd95e6ad7ea3c1d3350",
+                "url": "https://api.github.com/repos/symfony/console/zipball/273fd29ff30ba0a88ca5fb83f7cf1ab69306adae",
+                "reference": "273fd29ff30ba0a88ca5fb83f7cf1ab69306adae",
                 "shasum": ""
             },
             "require": {
                 "terminal"
             ],
             "support": {
-                "source": "https://github.com/symfony/console/tree/v6.4.24"
+                "source": "https://github.com/symfony/console/tree/v6.4.25"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-30T10:38:54+00:00"
+            "time": "2025-08-22T10:21:53+00:00"
         },
         {
             "name": "symfony/css-selector",
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v7.3.0",
+            "version": "v7.3.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher.git",
-                "reference": "497f73ac996a598c92409b44ac43b6690c4f666d"
+                "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d",
-                "reference": "497f73ac996a598c92409b44ac43b6690c4f666d",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191",
+                "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191",
                 "shasum": ""
             },
             "require": {
             "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0"
+                "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.3"
             },
             "funding": [
                 {
                     "url": "https://github.com/fabpot",
                     "type": "github"
                 },
+                {
+                    "url": "https://github.com/nicolas-grekas",
+                    "type": "github"
+                },
                 {
                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-04-22T09:11:45+00:00"
+            "time": "2025-08-13T11:49:31+00:00"
         },
         {
             "name": "symfony/event-dispatcher-contracts",
         },
         {
             "name": "symfony/http-client",
-            "version": "v6.4.24",
+            "version": "v6.4.25",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-client.git",
-                "reference": "6d78fe8abecd547c159b8a49f7c88610630b7da2"
+                "reference": "b8e9dce2d8acba3c32af467bb58e0c3656886181"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-client/zipball/6d78fe8abecd547c159b8a49f7c88610630b7da2",
-                "reference": "6d78fe8abecd547c159b8a49f7c88610630b7da2",
+                "url": "https://api.github.com/repos/symfony/http-client/zipball/b8e9dce2d8acba3c32af467bb58e0c3656886181",
+                "reference": "b8e9dce2d8acba3c32af467bb58e0c3656886181",
                 "shasum": ""
             },
             "require": {
                 "psr/log": "^1|^2|^3",
                 "symfony/deprecation-contracts": "^2.5|^3",
                 "symfony/http-client-contracts": "~3.4.4|^3.5.2",
+                "symfony/polyfill-php83": "^1.29",
                 "symfony/service-contracts": "^2.5|^3"
             },
             "conflict": {
                 "http"
             ],
             "support": {
-                "source": "https://github.com/symfony/http-client/tree/v6.4.24"
+                "source": "https://github.com/symfony/http-client/tree/v6.4.25"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-14T16:38:25+00:00"
+            "time": "2025-08-27T07:01:16+00:00"
         },
         {
             "name": "symfony/http-client-contracts",
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v6.4.24",
+            "version": "v6.4.25",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-foundation.git",
-                "reference": "0341e41d8d8830c31a1dff5cbc5bdb3ec872a073"
+                "reference": "6bc974c0035b643aa497c58d46d9e25185e4b272"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/0341e41d8d8830c31a1dff5cbc5bdb3ec872a073",
-                "reference": "0341e41d8d8830c31a1dff5cbc5bdb3ec872a073",
+                "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6bc974c0035b643aa497c58d46d9e25185e4b272",
+                "reference": "6bc974c0035b643aa497c58d46d9e25185e4b272",
                 "shasum": ""
             },
             "require": {
             "description": "Defines an object-oriented layer for the HTTP specification",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/http-foundation/tree/v6.4.24"
+                "source": "https://github.com/symfony/http-foundation/tree/v6.4.25"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-10T08:14:14+00:00"
+            "time": "2025-08-20T06:48:20+00:00"
         },
         {
             "name": "symfony/http-kernel",
-            "version": "v6.4.24",
+            "version": "v6.4.25",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-kernel.git",
-                "reference": "b81dcdbe34b8e8f7b3fc7b2a47fa065d5bf30726"
+                "reference": "a0ee3cea5cabf4ed960fd2ef57668ceeacdb6e15"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b81dcdbe34b8e8f7b3fc7b2a47fa065d5bf30726",
-                "reference": "b81dcdbe34b8e8f7b3fc7b2a47fa065d5bf30726",
+                "url": "https://api.github.com/repos/symfony/http-kernel/zipball/a0ee3cea5cabf4ed960fd2ef57668ceeacdb6e15",
+                "reference": "a0ee3cea5cabf4ed960fd2ef57668ceeacdb6e15",
                 "shasum": ""
             },
             "require": {
             "description": "Provides a structured process for converting a Request into a Response",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/http-kernel/tree/v6.4.24"
+                "source": "https://github.com/symfony/http-kernel/tree/v6.4.25"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-31T09:23:30+00:00"
+            "time": "2025-08-29T07:55:45+00:00"
         },
         {
             "name": "symfony/mailer",
-            "version": "v6.4.24",
+            "version": "v6.4.25",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/mailer.git",
-                "reference": "b4d7fa2c69641109979ed06e98a588d245362062"
+                "reference": "628b43b45a3e6b15c8a633fb22df547ed9b492a2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/mailer/zipball/b4d7fa2c69641109979ed06e98a588d245362062",
-                "reference": "b4d7fa2c69641109979ed06e98a588d245362062",
+                "url": "https://api.github.com/repos/symfony/mailer/zipball/628b43b45a3e6b15c8a633fb22df547ed9b492a2",
+                "reference": "628b43b45a3e6b15c8a633fb22df547ed9b492a2",
                 "shasum": ""
             },
             "require": {
             "description": "Helps sending emails",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/mailer/tree/v6.4.24"
+                "source": "https://github.com/symfony/mailer/tree/v6.4.25"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-24T08:25:04+00:00"
+            "time": "2025-08-13T09:41:44+00:00"
         },
         {
             "name": "symfony/mime",
         },
         {
             "name": "symfony/options-resolver",
-            "version": "v7.3.2",
+            "version": "v7.3.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/options-resolver.git",
-                "reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37"
+                "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/options-resolver/zipball/119bcf13e67dbd188e5dbc74228b1686f66acd37",
-                "reference": "119bcf13e67dbd188e5dbc74228b1686f66acd37",
+                "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d",
+                "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d",
                 "shasum": ""
             },
             "require": {
                 "options"
             ],
             "support": {
-                "source": "https://github.com/symfony/options-resolver/tree/v7.3.2"
+                "source": "https://github.com/symfony/options-resolver/tree/v7.3.3"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-15T11:36:08+00:00"
+            "time": "2025-08-05T10:16:07+00:00"
         },
         {
             "name": "symfony/polyfill-ctype",
             ],
             "time": "2025-07-08T02:45:35+00:00"
         },
+        {
+            "name": "symfony/polyfill-php84",
+            "version": "v1.33.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-php84.git",
+                "reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
+                "reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.2"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "url": "https://github.com/symfony/polyfill",
+                    "name": "symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Php84\\": ""
+                },
+                "classmap": [
+                    "Resources/stubs"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/nicolas-grekas",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2025-06-24T13:30:11+00:00"
+        },
         {
             "name": "symfony/polyfill-uuid",
             "version": "v1.33.0",
         },
         {
             "name": "symfony/process",
-            "version": "v6.4.24",
+            "version": "v6.4.25",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/process.git",
-                "reference": "8eb6dc555bfb49b2703438d5de65cc9f138ff50b"
+                "reference": "6be2f0c9ab3428587c07bed03aa9e3d1b823c6c8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/process/zipball/8eb6dc555bfb49b2703438d5de65cc9f138ff50b",
-                "reference": "8eb6dc555bfb49b2703438d5de65cc9f138ff50b",
+                "url": "https://api.github.com/repos/symfony/process/zipball/6be2f0c9ab3428587c07bed03aa9e3d1b823c6c8",
+                "reference": "6be2f0c9ab3428587c07bed03aa9e3d1b823c6c8",
                 "shasum": ""
             },
             "require": {
             "description": "Executes commands in sub-processes",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/process/tree/v6.4.24"
+                "source": "https://github.com/symfony/process/tree/v6.4.25"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-10T08:14:14+00:00"
+            "time": "2025-08-14T06:23:17+00:00"
         },
         {
             "name": "symfony/routing",
         },
         {
             "name": "symfony/serializer",
-            "version": "v7.3.2",
+            "version": "v7.3.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/serializer.git",
-                "reference": "0ed011583fd24899fa003abf77c45d4a901714da"
+                "reference": "5608b04d8daaf29432d76ecc618b0fac169c2dfb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/serializer/zipball/0ed011583fd24899fa003abf77c45d4a901714da",
-                "reference": "0ed011583fd24899fa003abf77c45d4a901714da",
+                "url": "https://api.github.com/repos/symfony/serializer/zipball/5608b04d8daaf29432d76ecc618b0fac169c2dfb",
+                "reference": "5608b04d8daaf29432d76ecc618b0fac169c2dfb",
                 "shasum": ""
             },
             "require": {
                 "php": ">=8.2",
                 "symfony/deprecation-contracts": "^2.5|^3",
-                "symfony/polyfill-ctype": "~1.8"
+                "symfony/polyfill-ctype": "~1.8",
+                "symfony/polyfill-php84": "^1.30"
             },
             "conflict": {
                 "phpdocumentor/reflection-docblock": "<3.2.2",
             "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/serializer/tree/v7.3.2"
+                "source": "https://github.com/symfony/serializer/tree/v7.3.3"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-26T13:07:17+00:00"
+            "time": "2025-08-27T11:34:33+00:00"
         },
         {
             "name": "symfony/service-contracts",
         },
         {
             "name": "symfony/string",
-            "version": "v7.3.2",
+            "version": "v7.3.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/string.git",
-                "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca"
+                "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/string/zipball/42f505aff654e62ac7ac2ce21033818297ca89ca",
-                "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca",
+                "url": "https://api.github.com/repos/symfony/string/zipball/17a426cce5fd1f0901fefa9b2a490d0038fd3c9c",
+                "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c",
                 "shasum": ""
             },
             "require": {
                 "utf8"
             ],
             "support": {
-                "source": "https://github.com/symfony/string/tree/v7.3.2"
+                "source": "https://github.com/symfony/string/tree/v7.3.3"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-10T08:47:49+00:00"
+            "time": "2025-08-25T06:35:40+00:00"
         },
         {
             "name": "symfony/translation",
         },
         {
             "name": "symfony/validator",
-            "version": "v7.3.2",
+            "version": "v7.3.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/validator.git",
-                "reference": "e5cc60fd44aab8e1d662fc0d954da322c2e08b43"
+                "reference": "a2f26d7c122393db75a2d41435ad8251250f8bc6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/validator/zipball/e5cc60fd44aab8e1d662fc0d954da322c2e08b43",
-                "reference": "e5cc60fd44aab8e1d662fc0d954da322c2e08b43",
+                "url": "https://api.github.com/repos/symfony/validator/zipball/a2f26d7c122393db75a2d41435ad8251250f8bc6",
+                "reference": "a2f26d7c122393db75a2d41435ad8251250f8bc6",
                 "shasum": ""
             },
             "require": {
             "description": "Provides tools to validate values",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/validator/tree/v7.3.2"
+                "source": "https://github.com/symfony/validator/tree/v7.3.3"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-29T20:02:46+00:00"
+            "time": "2025-08-27T11:34:33+00:00"
         },
         {
             "name": "symfony/var-dumper",
-            "version": "v6.4.24",
+            "version": "v6.4.25",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/var-dumper.git",
-                "reference": "aa29484ce0544bd69fa9f0df902e5ed7b7fe5034"
+                "reference": "c6cd92486e9fc32506370822c57bc02353a5a92c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/aa29484ce0544bd69fa9f0df902e5ed7b7fe5034",
-                "reference": "aa29484ce0544bd69fa9f0df902e5ed7b7fe5034",
+                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c6cd92486e9fc32506370822c57bc02353a5a92c",
+                "reference": "c6cd92486e9fc32506370822c57bc02353a5a92c",
                 "shasum": ""
             },
             "require": {
                 "dump"
             ],
             "support": {
-                "source": "https://github.com/symfony/var-dumper/tree/v6.4.24"
+                "source": "https://github.com/symfony/var-dumper/tree/v6.4.25"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-29T18:40:01+00:00"
+            "time": "2025-08-13T09:41:44+00:00"
         },
         {
             "name": "symfony/var-exporter",
-            "version": "v7.3.2",
+            "version": "v7.3.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/var-exporter.git",
-                "reference": "05b3e90654c097817325d6abd284f7938b05f467"
+                "reference": "d4dfcd2a822cbedd7612eb6fbd260e46f87b7137"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-exporter/zipball/05b3e90654c097817325d6abd284f7938b05f467",
-                "reference": "05b3e90654c097817325d6abd284f7938b05f467",
+                "url": "https://api.github.com/repos/symfony/var-exporter/zipball/d4dfcd2a822cbedd7612eb6fbd260e46f87b7137",
+                "reference": "d4dfcd2a822cbedd7612eb6fbd260e46f87b7137",
                 "shasum": ""
             },
             "require": {
                 "serialize"
             ],
             "support": {
-                "source": "https://github.com/symfony/var-exporter/tree/v7.3.2"
+                "source": "https://github.com/symfony/var-exporter/tree/v7.3.3"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-10T08:47:49+00:00"
+            "time": "2025-08-18T13:10:53+00:00"
         },
         {
             "name": "symfony/yaml",
-            "version": "v7.3.2",
+            "version": "v7.3.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/yaml.git",
-                "reference": "b8d7d868da9eb0919e99c8830431ea087d6aae30"
+                "reference": "d4f4a66866fe2451f61296924767280ab5732d9d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/yaml/zipball/b8d7d868da9eb0919e99c8830431ea087d6aae30",
-                "reference": "b8d7d868da9eb0919e99c8830431ea087d6aae30",
+                "url": "https://api.github.com/repos/symfony/yaml/zipball/d4f4a66866fe2451f61296924767280ab5732d9d",
+                "reference": "d4f4a66866fe2451f61296924767280ab5732d9d",
                 "shasum": ""
             },
             "require": {
             "description": "Loads and dumps YAML files",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/yaml/tree/v7.3.2"
+                "source": "https://github.com/symfony/yaml/tree/v7.3.3"
             },
             "funding": [
                 {
                     "type": "tidelift"
                 }
             ],
-            "time": "2025-07-10T08:47:49+00:00"
+            "time": "2025-08-27T11:34:33+00:00"
         },
         {
             "name": "theafolayan/listmonk-laravel",
             },
             "time": "2024-12-21T16:25:41+00:00"
         },
+        {
+            "name": "typesense/typesense-php",
+            "version": "v5.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/typesense/typesense-php.git",
+                "reference": "0e8dee542c05b201becf4734319075e6c4d540b3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/typesense/typesense-php/zipball/0e8dee542c05b201becf4734319075e6c4d540b3",
+                "reference": "0e8dee542c05b201becf4734319075e6c4d540b3",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "monolog/monolog": "^2.1 || ^3.0 || ^3.3",
+                "nyholm/psr7": "^1.3",
+                "php": ">=7.4",
+                "php-http/client-common": "^1.0 || ^2.3",
+                "php-http/discovery": "^1.0",
+                "php-http/httplug": "^1.0 || ^2.2",
+                "psr/http-client-implementation": "^1.0",
+                "psr/http-factory": "^1.0",
+                "psr/http-message": "^1.0 || ^2.0"
+            },
+            "require-dev": {
+                "mockery/mockery": "^1.6",
+                "phpunit/phpunit": "^11.2",
+                "squizlabs/php_codesniffer": "3.*",
+                "symfony/http-client": "^5.2"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Typesense\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Typesense",
+                    "email": "contact@typesense.org",
+                    "homepage": "https://typesense.org",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Abdullah Al-Faqeir",
+                    "email": "abdullah@devloops.net",
+                    "homepage": "https://www.devloops.net",
+                    "role": "Developer"
+                }
+            ],
+            "description": "PHP client for Typesense Search Server: https://github.com/typesense/typesense",
+            "homepage": "https://github.com/typesense/typesense-php",
+            "support": {
+                "docs": "https://typesense.org/api",
+                "issues": "https://github.com/typesense/typesense-php/issues",
+                "source": "https://github.com/typesense/typesense-php"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/typesense",
+                    "type": "github"
+                }
+            ],
+            "time": "2025-05-05T17:35:26+00:00"
+        },
         {
             "name": "umpirsky/country-list",
             "version": "2.0.6",
         },
         {
             "name": "phpstan/phpdoc-parser",
-            "version": "2.2.0",
+            "version": "2.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpstan/phpdoc-parser.git",
-                "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8"
+                "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8",
-                "reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8",
+                "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495",
+                "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495",
                 "shasum": ""
             },
             "require": {
             "description": "PHPDoc parser with support for nullable, intersection and generic types",
             "support": {
                 "issues": "https://github.com/phpstan/phpdoc-parser/issues",
-                "source": "https://github.com/phpstan/phpdoc-parser/tree/2.2.0"
+                "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0"
             },
-            "time": "2025-07-13T07:04:09+00:00"
+            "time": "2025-08-30T15:50:23+00:00"
         },
         {
             "name": "phpunit/php-code-coverage",