REDIS_PORT=6379
MAIL_DRIVER=smtp
-MAIL_HOST=mail2.cubedesigners.com
-MAIL_PORT=587
-MAIL_USERNAME=workshop@cubedesigners.com
-MAIL_PASSWORD=4zrmk4Hu9HH97n7UiW5
-MAIL_ENCRYPTION=tls
+MAIL_HOST=postal.cubedesigners.com
+MAIL_PORT=25
+MAIL_USERNAME=cubedesigners/fluidbook-toolbox-dev
+MAIL_PASSWORD=jgqyC9RxBxAM40C5zoJj0WVT
+MAIL_ENCRYPTION=false
MAIL_FROM_ADDRESS=toolbox+alpha@fluidbook.com
MAIL_FROM_NAME="[ALPHA] Fluidbook Toolbox"
MAIL_BCC_ALL=test+toolboxalpha@cubedesigners.com
REDIS_PORT=6379
MAIL_DRIVER=smtp
-MAIL_HOST=mail2.cubedesigners.com
-MAIL_PORT=587
-MAIL_USERNAME=workshop@cubedesigners.com
-MAIL_PASSWORD=4zrmk4Hu9HH97n7UiW5
-MAIL_ENCRYPTION=tls
+MAIL_HOST=postal.cubedesigners.com
+MAIL_PORT=25
+MAIL_USERNAME=cubedesigners/fluidbook-toolbox-dev
+MAIL_PASSWORD=jgqyC9RxBxAM40C5zoJj0WVT
+MAIL_ENCRYPTION=false
MAIL_FROM_ADDRESS=toolbox+dev@fluidbook.com
MAIL_FROM_NAME="[DEV] Fluidbook Toolbox"
MAIL_BCC_ALL=test+toolboxdev@cubedesigners.com
MAIL_TEAM_NAME=Fluidbook
-MAILJET_API_KEY=ca110b35f8735c223d69c9987c2ac47d
-MAILJET_API_SECRET=b289d0acb08e0fe56ce98ccf0dd1ed8b
+LISTMONK_BASE_URL=https://listmonk.cubedesigners.com
+LISTMONK_API_USER=fluidbooktoolbox
+LISTMONK_API_TOKEN=b289d0acb08e0fe56ce98ccf0dd1ed8b
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
REDIS_PORT=6379
MAIL_DRIVER=smtp
-MAIL_HOST=mail2.cubedesigners.com
-MAIL_PORT=587
-MAIL_USERNAME=workshop@cubedesigners.com
-MAIL_PASSWORD=4zrmk4Hu9HH97n7UiW5
-MAIL_ENCRYPTION=tls
+MAIL_HOST=postal.cubedesigners.com
+MAIL_PORT=25
+MAIL_USERNAME=cubedesigners/fluidbook-toolbox
+MAIL_PASSWORD=JzKxZdtN730yXwKRorTVDhaK
+MAIL_ENCRYPTION=false
MAIL_FROM_ADDRESS=toolbox@fluidbook.com
MAIL_FROM_NAME="Fluidbook Toolbox"
MAIL_BCC_ALL=test+toolbox@cubedesigners.com
RATE_PEOPLE_DAY=630
RATE_PEOPLE_HOUR=100
-MAILJET_API_KEY=ca110b35f8735c223d69c9987c2ac47d
-MAILJET_API_SECRET=b289d0acb08e0fe56ce98ccf0dd1ed8b
+LISTMONK_BASE_URL=https://listmonk.cubedesigners.com
+LISTMONK_API_USER=fluidbooktoolbox
+LISTMONK_API_TOKEN=f60zrw7kvialdQFlMCrMKLl49nlQSkEe
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
// Quotes
$schedule->command('fluidbook:quote --reminder')->weekdays()->at('10:00');
// Mailjet
- $schedule->command('job:dispatchNow MailjetSyncList')->dailyAt('5:00');
+ $schedule->command('job:dispatchNow ListmonkSyncList')->dailyAt('5:00');
}
$schedule->command('job:dispatchNow ProcessTotals')->everyTwoHours();
--- /dev/null
+<?php
+
+namespace App\Jobs;
+
+use App\Models\Company;
+use App\Models\User;
+use Cubedesigners\UserDatabase\Permissions;
+use DateTimeInterface;
+use Egulias\EmailValidator\EmailValidator;
+use Egulias\EmailValidator\Validation\DNSCheckValidation;
+use Egulias\EmailValidator\Validation\MultipleValidationWithAnd;
+use Egulias\EmailValidator\Validation\RFCValidation;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\DB;
+use Mailjet\Client;
+use Mailjet\Resources;
+use Theafolayan\ListmonkLaravel\Facades\Listmonk;
+
+class ListmonkSyncList extends Base
+{
+ const LIST_ID = '1';
+
+ const ENABLED = true;
+
+ const BATCH = 500;
+
+ /**
+ * @throws \Exception
+ */
+ public function handle()
+ {
+ //$this->syncStatusFromMailjet();
+ //dump('Synced status from mailjet');
+
+ dd(Listmonk::getSubscribers(['per_page' => 100000, 'page' => 1, 'list_id' => [self::LIST_ID]]));
+
+ $skippedCompanies = [];
+ $companies = [];
+ $contacts = ['addnoforce' => [], 'unsub' => [], 'remove' => []];
+
+ $validator = new EmailValidator();
+ $multipleValidations = new MultipleValidationWithAnd([
+ new RFCValidation(),
+ new DNSCheckValidation()
+ ]);
+
+ foreach (Company::withoutGlobalScopes()->get() as $company) {
+ if (!$company->created_ok) {
+ $skippedCompanies[] = $company->id;
+ continue;
+ }
+ /** @var Company $company */
+ $adminCompany = Permissions::getCompanyByUser($company->admin);
+ // Skip companies not directly managed by Cubedesigners
+ if ($adminCompany != 7 && !$company->marketing_force) {
+ $skippedCompanies[] = $company->id;
+ continue;
+ }
+ $companies[$company->id] = $company;
+ }
+
+ foreach (User::withoutGlobalScopes()->where('created_ok', '1')->where('enabled', '1')->get() as $user) {
+ if (in_array($user->company, $skippedCompanies) || !isset($companies[$user->company])) {
+ continue;
+ }
+
+ $c = $companies[$user->company];
+ $address = $user->address;
+ if (is_string($address)) {
+ $address = json_decode($address);
+ }
+ if (null === $address) {
+ $country = '';
+ } else {
+ $country = is_array($address) ? $address['country'] : $address->country;
+ }
+
+ $action = 'addnoforce';
+
+ if (str_ends_with($user->email, '@extranet.cubedesigners.com')) {
+ $action = 'remove';
+ }
+
+ if (!Cache::rememberForever('email_valid_' . $user->email, function () use ($user, $validator, $multipleValidations) {
+ return $validator->isValid($user->email, $multipleValidations);
+ })) {
+ continue;
+ }
+
+ if (!$user->marketing) {
+ $action = 'unsub';
+ }
+
+ $contact = [
+ 'email' => $user->email,
+ 'status' => 'enabled',
+ 'name' => trim($user->firstname . ' ' . $user->lastname),
+ 'preconfirm_subscriptions' => true,
+ 'lists' => [self::LIST_ID],
+ 'attribs' => [
+ 'toolbox_id' => $user->id,
+ 'firstname' => trim($user->firstname),
+ 'lastname' => trim($user->lastname),
+ 'company' => trim($c->name),
+ 'fluidbook' => $c->e1_ws_grade > 0 && $c->toolbox_access,
+ 'elearning' => (bool)$c->permissions_elearning,
+ 'locale' => $user->locale,
+ 'country' => $country,
+ 'last_project' => $c->c_last_project_date ? (new \DateTime($c->c_last_project_date))->format(DateTimeInterface::RFC3339) : '',
+ ]
+ ];
+
+ $contacts[$action][] = $contact;
+ }
+
+
+ foreach ($contacts as $action => $list) {
+ $this->addContactsToList($list, $action);
+ }
+
+ }
+
+ protected function deleteContacts()
+ {
+ $mj = static::_api();
+ $i = 0;
+ $remove = $this->getRecipientsList();
+ $emails = $this->getEmailsFromContactIDs($remove);
+ $contacts = [];
+ foreach ($emails as $email) {
+ $contacts[] = ['Email' => $email];
+ }
+ $this->addContactsToList($contacts, 'remove');
+ }
+
+ protected function getRecipientsList($filter = null)
+ {
+ $i = 0;
+ $res = [];
+ $mj = static::_api();
+
+
+ $filters = ['ContactsList' => static::LIST_ID,
+ 'Limit' => self::BATCH,
+ 'Offset' => 0];
+ if (null !== $filter) {
+ $filters = array_merge($filters, $filter);
+ }
+
+ while (true) {
+ $filters['Offset'] = $i * self::BATCH;
+ $response = $mj->get(Resources::$Listrecipient, ['filters' => $filters]);
+ foreach ($response->getData() as $contact) {
+ $res[] = $contact['ContactID'];
+ }
+
+ if ($response->getCount() < self::BATCH) {
+ break;
+ }
+
+ $i++;
+ }
+ return $res;
+ }
+
+ protected function getEmailsFromContactIDs($contactIDs)
+ {
+ $i = 0;
+ $res = [];
+ $mj = static::_api();
+
+ while (true) {
+ $response = $mj->get(Resources::$Contact, ['filters' => ['ContactsList' => static::LIST_ID,
+ 'Limit' => self::BATCH,
+ 'Offset' => $i * self::BATCH,
+ ]]);
+
+ foreach ($response->getData() as $contact) {
+ if (in_array($contact['ID'], $contactIDs)) {
+ $res[] = $contact['Email'];
+ }
+ }
+ if ($response->getCount() < self::BATCH) {
+ break;
+ }
+ $i++;
+ }
+ return $res;
+ }
+
+ protected function addContactsToList($contacts, $action = 'addnoforce')
+ {
+ if (empty($contacts)) {
+ return;
+ }
+ $body = [
+ 'Action' => $action,
+ 'Contacts' => $contacts
+ ];
+ $response = $mj->post(Resources::$ContactslistManagemanycontacts, ['id' => self::LIST_ID, 'body' => $body]);
+ $jobId = $response->getData()[0]['JobID'];
+
+ while (true) {
+ $check = $mj->get(Resources::$ContactslistManagemanycontacts, ['id' => self::LIST_ID, 'actionid' => (string)$jobId]);
+ $status = ($check->getData()[0]['Status']);
+ if ($status === 'Error') {
+ dd($check->getData()[0]);
+ } else if ($status === 'Completed') {
+ return;
+ }
+ dump($status);
+ sleep(2);
+ }
+ }
+
+ protected function syncStatusFromMailjet()
+ {
+ $mj = static::_api();
+ $i = 0;
+ $unsub = [];
+
+ $timestamp = time() - (3600 * 24 * 90); // 90 days in the past
+
+ // Check bounces
+ while (true) {
+ $response = $mj->get(Resources::$Bouncestatistics, ['filters' => [
+ 'Limit' => self::BATCH,
+ 'Offset' => $i * self::BATCH,
+ 'FromTS' => $timestamp,
+ ]]);
+
+ foreach ($response->getData() as $contact) {
+ if ($contact['IsBlocked'] || $contact['IsStatePermanent']) {
+ $unsub[] = $contact['ContactID'];
+ }
+ }
+
+ if ($response->getCount() < self::BATCH) {
+ break;
+ }
+ $i++;
+ }
+
+ // Check unsubscribed users
+ $filters = ['Unsub' => 'true', 'IsExcludedFromCampaigns' => 'true'];
+ foreach ($filters as $filter => $value) {
+ $unsub = array_merge($unsub, $this->getRecipientsList([$filter => $value]));
+ }
+
+ $unsubEmails = $this->getEmailsFromContactIDs($unsub);
+ DB::table('extranet_users.user')->whereIn('email', $unsubEmails)->update(['marketing' => 0]);
+ }
+}
+++ /dev/null
-<?php
-
-namespace App\Jobs;
-
-use App\Models\Company;
-use App\Models\User;
-use Cubedesigners\UserDatabase\Permissions;
-use DateTimeInterface;
-use Egulias\EmailValidator\EmailValidator;
-use Egulias\EmailValidator\Validation\DNSCheckValidation;
-use Egulias\EmailValidator\Validation\MultipleValidationWithAnd;
-use Egulias\EmailValidator\Validation\RFCValidation;
-use Illuminate\Support\Facades\Cache;
-use Illuminate\Support\Facades\DB;
-use Mailjet\Client;
-use Mailjet\Resources;
-
-class MailjetSyncList extends Base
-{
- const LIST_ID = '10296433';
-
- const ENABLED = false;
-
- const BATCH = 500;
-
- /**
- * @throws \Exception
- */
- public function handle()
- {
- if (!self::ENABLED) {
- $this->deleteContacts();
- return;
- }
-
- $this->syncStatusFromMailjet();
- dump('Synced status from mailjet');
-
- $skippedCompanies = [];
- $companies = [];
- $contacts = ['addnoforce' => [], 'unsub' => [], 'remove' => []];
-
- $validator = new EmailValidator();
- $multipleValidations = new MultipleValidationWithAnd([
- new RFCValidation(),
- new DNSCheckValidation()
- ]);
-
- foreach (Company::withoutGlobalScopes()->get() as $company) {
- if (!$company->created_ok) {
- $skippedCompanies[] = $company->id;
- continue;
- }
- /** @var Company $company */
- $adminCompany = Permissions::getCompanyByUser($company->admin);
- // Skip companies not directly managed by Cubedesigners
- if ($adminCompany != 7 && !$company->marketing_force) {
- $skippedCompanies[] = $company->id;
- continue;
- }
- $companies[$company->id] = $company;
- }
-
- foreach (User::withoutGlobalScopes()->where('created_ok', '1')->where('enabled', '1')->get() as $user) {
- if (in_array($user->company, $skippedCompanies) || !isset($companies[$user->company])) {
- continue;
- }
-
- $c = $companies[$user->company];
- $address = $user->address;
- if (is_string($address)) {
- $address = json_decode($address);
- }
- if (null === $address) {
- $country = '';
- } else {
- $country = is_array($address) ? $address['country'] : $address->country;
- }
-
- $action = 'addnoforce';
-
- if (str_ends_with($user->email, '@extranet.cubedesigners.com')) {
- $action = 'remove';
- }
-
- if (!Cache::rememberForever('email_valid_' . $user->email, function () use ($user, $validator, $multipleValidations) {
- return $validator->isValid($user->email, $multipleValidations);
- })) {
- continue;
- }
-
- if (!$user->marketing) {
- $action = 'unsub';
- }
-
- $contact = [
- 'Email' => $user->email,
- 'IsExcludedFromCampaigns' => 'false',
- 'Name' => trim($user->firstname . ' ' . $user->lastname),
- 'Properties' => [
- 'toolbox_id' => $user->id,
- 'firstname' => trim($user->firstname),
- 'lastname' => trim($user->lastname),
- 'company' => trim($c->name),
- 'fluidbook' => $c->e1_ws_grade > 0 && $c->toolbox_access,
- 'elearning' => (bool)$c->permissions_elearning,
- 'locale' => $user->locale,
- 'country' => $country,
- 'last_project' => $c->c_last_project_date ? (new \DateTime($c->c_last_project_date))->format(DateTimeInterface::RFC3339) : '',
- ]
- ];
-
- $contacts[$action][] = $contact;
- }
-
-
- foreach ($contacts as $action => $list) {
- $this->addContactsToList($list, $action);
- }
-
- }
-
- protected function deleteContacts()
- {
- $mj = static::_api();
- $i = 0;
- $remove = $this->getRecipientsList();
- $emails=$this->getEmailsFromContactIDs($remove);
- $contacts = [];
- foreach ($emails as $email) {
- $contacts[] = ['Email' => $email];
- }
- $this->addContactsToList($contacts, 'remove');
- }
-
- protected function getRecipientsList($filter = null)
- {
- $i = 0;
- $res = [];
- $mj = static::_api();
-
-
- $filters = ['ContactsList' => static::LIST_ID,
- 'Limit' => self::BATCH,
- 'Offset' => 0];
- if (null !== $filter) {
- $filters = array_merge($filters, $filter);
- }
-
- while (true) {
- $filters['Offset'] = $i * self::BATCH;
- $response = $mj->get(Resources::$Listrecipient, ['filters' => $filters]);
- foreach ($response->getData() as $contact) {
- $res[] = $contact['ContactID'];
- }
-
- if ($response->getCount() < self::BATCH) {
- break;
- }
-
- $i++;
- }
- return $res;
- }
-
- protected function getEmailsFromContactIDs($contactIDs)
- {
- $i = 0;
- $res = [];
- $mj = static::_api();
-
- while (true) {
- $response = $mj->get(Resources::$Contact, ['filters' => ['ContactsList' => static::LIST_ID,
- 'Limit' => self::BATCH,
- 'Offset' => $i * self::BATCH,
- ]]);
-
- foreach ($response->getData() as $contact) {
- if (in_array($contact['ID'], $contactIDs)) {
- $res[] = $contact['Email'];
- }
- }
- if ($response->getCount() < self::BATCH) {
- break;
- }
- $i++;
- }
- return $res;
- }
-
- protected function addContactsToList($contacts, $action = 'addnoforce')
- {
- if (empty($contacts)) {
- return;
- }
- $mj = static::_api();
- $body = [
- 'Action' => $action,
- 'Contacts' => $contacts
- ];
- $response = $mj->post(Resources::$ContactslistManagemanycontacts, ['id' => self::LIST_ID, 'body' => $body]);
- $jobId = $response->getData()[0]['JobID'];
-
- while (true) {
- $check = $mj->get(Resources::$ContactslistManagemanycontacts, ['id' => self::LIST_ID, 'actionid' => (string)$jobId]);
- $status = ($check->getData()[0]['Status']);
- if ($status === 'Error') {
- dd($check->getData()[0]);
- } else if ($status === 'Completed') {
- return;
- }
- dump($status);
- sleep(2);
- }
- }
-
- protected function syncStatusFromMailjet()
- {
- $mj = static::_api();
- $i = 0;
- $unsub = [];
-
- $timestamp = time() - (3600 * 24 * 90); // 90 days in the past
-
- // Check bounces
- while (true) {
- $response = $mj->get(Resources::$Bouncestatistics, ['filters' => [
- 'Limit' => self::BATCH,
- 'Offset' => $i * self::BATCH,
- 'FromTS' => $timestamp,
- ]]);
-
- foreach ($response->getData() as $contact) {
- if ($contact['IsBlocked'] || $contact['IsStatePermanent']) {
- $unsub[] = $contact['ContactID'];
- }
- }
-
- if ($response->getCount() < self::BATCH) {
- break;
- }
- $i++;
- }
-
- // Check unsubscribed users
- $filters = ['Unsub' => 'true', 'IsExcludedFromCampaigns' => 'true'];
- foreach ($filters as $filter => $value) {
- $unsub = array_merge($unsub, $this->getRecipientsList([$filter => $value]));
- }
-
- $unsubEmails = $this->getEmailsFromContactIDs($unsub);
- DB::table('extranet_users.user')->whereIn('email', $unsubEmails)->update(['marketing' => 0]);
- }
-
- /**
- * @return Client
- */
- protected static function _api($call = true, $version = 'v3')
- {
- return new \Mailjet\Client(env('MAILJET_API_KEY'), env('MAILJET_API_SECRET'), $call, ['version' => $version]);
- }
-}
"rustici-software/scormcloud-api-v2-client-php": "^2.1.0",
"simplesoftwareio/simple-qrcode": "^4.2",
"symfony/http-client": "^v6.4.0",
+ "theafolayan/listmonk-laravel": "^1.3",
"voku/simple_html_dom": "^4.8"
},
"require-dev": {
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "86f3969e7c9517948cd163134578cf66",
+ "content-hash": "674f394b07cd9069af87322406565da9",
"packages": [
{
"name": "archtechx/enums",
"source": {
"type": "git",
"url": "git://git.cubedesigners.com/fluidbook_tools.git",
- "reference": "4847a6faf6184e235b290babce1d1c72ad54ff22"
+ "reference": "c06d81f8c352dbf896da52c6168aaf9b625da7b1"
},
"dist": {
"type": "tar",
- "url": "https://composer.cubedesigners.com/dist/fluidbook/tools/fluidbook-tools-dev-master-135a28.tar",
- "reference": "4847a6faf6184e235b290babce1d1c72ad54ff22",
- "shasum": "22a9e68c5c14e5d6c51b4ef205accbdd6fe2f765"
+ "url": "https://composer.cubedesigners.com/dist/fluidbook/tools/fluidbook-tools-dev-master-acf208.tar",
+ "reference": "c06d81f8c352dbf896da52c6168aaf9b625da7b1",
+ "shasum": "f2c41ec290bbb23ce83084fe6d724f3b88ace0cd"
},
"require": {
"barryvdh/laravel-debugbar": "*",
}
],
"description": "Fluidbook Tools",
- "time": "2025-02-28T16:32:27+00:00"
+ "time": "2025-03-04T16:42:05+00:00"
},
{
"name": "fpdf/fpdf",
},
{
"name": "graham-campbell/markdown",
- "version": "v15.2.0",
+ "version": "v15.3.0",
"source": {
"type": "git",
"url": "https://github.com/GrahamCampbell/Laravel-Markdown.git",
- "reference": "d594fc197b9068de5e234a890be361807a1ab34f"
+ "reference": "042c23ddc5bde61ed09b77a8a17119d70c8e8419"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/GrahamCampbell/Laravel-Markdown/zipball/d594fc197b9068de5e234a890be361807a1ab34f",
- "reference": "d594fc197b9068de5e234a890be361807a1ab34f",
+ "url": "https://api.github.com/repos/GrahamCampbell/Laravel-Markdown/zipball/042c23ddc5bde61ed09b77a8a17119d70c8e8419",
+ "reference": "042c23ddc5bde61ed09b77a8a17119d70c8e8419",
"shasum": ""
},
"require": {
"illuminate/filesystem": "^8.75 || ^9.0 || ^10.0 || ^11.0",
"illuminate/support": "^8.75 || ^9.0 || ^10.0 || ^11.0",
"illuminate/view": "^8.75 || ^9.0 || ^10.0 || ^11.0",
- "league/commonmark": "^2.4.2",
+ "league/commonmark": "^2.6.1",
"php": "^7.4.15 || ^8.0.2"
},
"require-dev": {
- "graham-campbell/analyzer": "^4.1",
- "graham-campbell/testbench": "^6.1",
+ "graham-campbell/analyzer": "^4.2.1",
+ "graham-campbell/testbench": "^6.2",
"mockery/mockery": "^1.6.6",
"phpunit/phpunit": "^9.6.17 || ^10.5.13"
},
],
"support": {
"issues": "https://github.com/GrahamCampbell/Laravel-Markdown/issues",
- "source": "https://github.com/GrahamCampbell/Laravel-Markdown/tree/v15.2.0"
+ "source": "https://github.com/GrahamCampbell/Laravel-Markdown/tree/v15.3.0"
},
"funding": [
{
"type": "tidelift"
}
],
- "time": "2024-03-17T23:07:39+00:00"
+ "time": "2025-03-02T22:13:22+00:00"
},
{
"name": "graham-campbell/result-type",
},
{
"name": "ramsey/collection",
- "version": "2.0.0",
+ "version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/ramsey/collection.git",
- "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5"
+ "reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5",
- "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5",
+ "url": "https://api.github.com/repos/ramsey/collection/zipball/3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109",
+ "reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109",
"shasum": ""
},
"require": {
},
"require-dev": {
"captainhook/plugin-composer": "^5.3",
- "ergebnis/composer-normalize": "^2.28.3",
- "fakerphp/faker": "^1.21",
+ "ergebnis/composer-normalize": "^2.45",
+ "fakerphp/faker": "^1.24",
"hamcrest/hamcrest-php": "^2.0",
- "jangregor/phpstan-prophecy": "^1.0",
- "mockery/mockery": "^1.5",
+ "jangregor/phpstan-prophecy": "^2.1",
+ "mockery/mockery": "^1.6",
"php-parallel-lint/php-console-highlighter": "^1.0",
- "php-parallel-lint/php-parallel-lint": "^1.3",
- "phpcsstandards/phpcsutils": "^1.0.0-rc1",
- "phpspec/prophecy-phpunit": "^2.0",
- "phpstan/extension-installer": "^1.2",
- "phpstan/phpstan": "^1.9",
- "phpstan/phpstan-mockery": "^1.1",
- "phpstan/phpstan-phpunit": "^1.3",
- "phpunit/phpunit": "^9.5",
- "psalm/plugin-mockery": "^1.1",
- "psalm/plugin-phpunit": "^0.18.4",
- "ramsey/coding-standard": "^2.0.3",
- "ramsey/conventional-commits": "^1.3",
- "vimeo/psalm": "^5.4"
+ "php-parallel-lint/php-parallel-lint": "^1.4",
+ "phpspec/prophecy-phpunit": "^2.3",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5",
+ "ramsey/coding-standard": "^2.3",
+ "ramsey/conventional-commits": "^1.6",
+ "roave/security-advisories": "dev-latest"
},
"type": "library",
"extra": {
],
"support": {
"issues": "https://github.com/ramsey/collection/issues",
- "source": "https://github.com/ramsey/collection/tree/2.0.0"
+ "source": "https://github.com/ramsey/collection/tree/2.1.0"
},
- "funding": [
- {
- "url": "https://github.com/ramsey",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/ramsey/collection",
- "type": "tidelift"
- }
- ],
- "time": "2022-12-31T21:50:55+00:00"
+ "time": "2025-03-02T04:48:29+00:00"
},
{
"name": "ramsey/uuid",
},
{
"name": "rickselby/laravel-gate-cache",
- "version": "3.8.0",
+ "version": "3.9.0",
"source": {
"type": "git",
"url": "https://github.com/rickselby/laravel-gate-cache.git",
- "reference": "d19bc9aaaffa5853c531e76bc19330dca4a5c606"
+ "reference": "6403cffb8d8082ff9b2944d3f481ce53c5aa9426"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/rickselby/laravel-gate-cache/zipball/d19bc9aaaffa5853c531e76bc19330dca4a5c606",
- "reference": "d19bc9aaaffa5853c531e76bc19330dca4a5c606",
+ "url": "https://api.github.com/repos/rickselby/laravel-gate-cache/zipball/6403cffb8d8082ff9b2944d3f481ce53c5aa9426",
+ "reference": "6403cffb8d8082ff9b2944d3f481ce53c5aa9426",
"shasum": ""
},
"require": {
- "illuminate/auth": "10.*|11.*",
- "illuminate/contracts": "10.*|11.*"
+ "illuminate/auth": "^10.0|^11.0|^12.0",
+ "illuminate/contracts": "^10.0|^11.0|^12.0"
},
"require-dev": {
"graham-campbell/testbench": "^6.1",
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^10.0|^11.0"
},
"type": "library",
"extra": {
"description": "Add a per-request caching layer to Laravel's Gate",
"support": {
"issues": "https://github.com/rickselby/laravel-gate-cache/issues",
- "source": "https://github.com/rickselby/laravel-gate-cache/tree/3.8.0"
+ "source": "https://github.com/rickselby/laravel-gate-cache/tree/3.9.0"
},
- "time": "2024-03-14T12:27:24+00:00"
+ "time": "2025-03-04T19:22:49+00:00"
},
{
"name": "rodneyrehm/plist",
],
"time": "2025-01-07T12:55:42+00:00"
},
+ {
+ "name": "theafolayan/listmonk-laravel",
+ "version": "1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theafolayan/listmonk-laravel.git",
+ "reference": "80b17cc74e857fa884fc9394d19889b5470dd7ad"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theafolayan/listmonk-laravel/zipball/80b17cc74e857fa884fc9394d19889b5470dd7ad",
+ "reference": "80b17cc74e857fa884fc9394d19889b5470dd7ad",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "^7.0",
+ "illuminate/support": "^8.0|^9.0|^10.0",
+ "php": "^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "aliases": {
+ "Listmonk": "Theafolayan\\ListmonkLaravel\\Facades\\Listmonk"
+ },
+ "providers": [
+ "Theafolayan\\ListmonkLaravel\\ListmonkServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Theafolayan\\ListmonkLaravel\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "theafolayan",
+ "email": "theafolayan@gmail.com"
+ }
+ ],
+ "description": "A Laravel package for interacting with the Listmonk API",
+ "support": {
+ "issues": "https://github.com/theafolayan/listmonk-laravel/issues",
+ "source": "https://github.com/theafolayan/listmonk-laravel/tree/v1.3.0"
+ },
+ "time": "2025-02-04T18:37:57+00:00"
+ },
{
"name": "tijsverkoyen/css-to-inline-styles",
"version": "v2.3.0",
--- /dev/null
+<?php
+
+return [
+ 'base_url' => env('LISTMONK_BASE_URL', 'http://localhost:9000'),
+ 'api_user' => env('LISTMONK_API_USER', 'default_user'),
+ 'api_token' => env('LISTMONK_API_TOKEN', 'your-token'),
+];