Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
62aa707
Update to 5.x (#338)
volha-pivavarchyk Jan 13, 2025
f9c3d1d
fix: Resolve contact tabs not being searchable and pagination not wor…
driskell Jul 2, 2025
f49fc5d
fix(DynamicContentSubscriber): complete Mautic 5 migration of filter …
edouard-mangel Mar 9, 2026
6f22f41
refactor(ContactFilterMatcher): remove class_alias pattern, use polyf…
edouard-mangel Mar 9, 2026
8c8f300
refactor(config): remove explicit service definitions, use autowiring
edouard-mangel Mar 10, 2026
e49bc8d
refactor(ContactFilterMatcher): use #[Autowire] for scalar parameter
edouard-mangel Mar 11, 2026
442f0af
test(ContactFilterMatcher): add unit tests
edouard-mangel Mar 11, 2026
3a9335a
fix(ContactFilterMatcher): replace deprecated DBAL execute() with exe…
edouard-mangel Mar 11, 2026
7227295
fix(MatchFilterForLeadTrait): handle empty operator when no custom it…
edouard-mangel Mar 11, 2026
63639a8
fix(ContactFilterMatcher): replace #[Autowire] with explicit arg bind…
edouard-mangel Mar 11, 2026
57cf15a
ci: add fix/** branch trigger and workflow_dispatch for local testing
edouard-mangel Mar 11, 2026
4878ed9
fix(cs): remove extra blank line, extra parentheses, and PHP 8.1 inte…
edouard-mangel Mar 11, 2026
ecd58ed
fix(tests): remove MAUTIC_TABLE_PREFIX define from test file (defined…
edouard-mangel Mar 11, 2026
c7302cb
fix(phpstan): add baseline entry for transformFilterDataForLeadPolyfi…
edouard-mangel Mar 11, 2026
6002c35
refactor: apply Rector rules (constructor promotion, str_starts_with,…
edouard-mangel Mar 11, 2026
99974b5
fix(phpstan): suppress array element type errors for transformFilterD…
edouard-mangel Mar 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
150 changes: 150 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
name: Mautic Build and Test

on:
push:
branches:
- staging # Main branch
- '[0-9]+\.[0-9]+'
- development
- beta
- 'fix/**'
pull_request:
workflow_dispatch:

env:
PLUGIN_DIR: plugins/CustomObjectsBundle # Same as extra.install-directory-name in composer.json

jobs:
phpunit:
runs-on: ubuntu-latest

strategy:
matrix:
php-versions: ['8.0'] # The supported PHP versions
db-types: ['mysql'] # can be: ['mysql', 'mariadb'] but not necessary for this plugin that does not add any DB schema
mautic-versions: ['5.1'] # The supported Mautic versions

name: Tests on PHP ${{ matrix.php-versions }}, ${{ matrix.db-types }}, Mautic ${{ matrix.mautic-versions }}

services:
database:
image: ${{ matrix.db-types == 'mysql' && 'mysql:8.0' || 'mariadb:10.3' }}
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: mautictest
ports:
- 3306
options: >-
--shm-size=2gb
--name=${{ matrix.db-types }}
--tmpfs=/var/lib/mysql
--health-cmd="mysqladmin ping"
--health-interval=10s
--health-timeout=5s
--health-retries=3

steps:
- name: Checkout Mautic
uses: actions/checkout@v4
with:
repository: mautic/mautic
ref: ${{ matrix.mautic-versions }}

- name: Checkout this plugin
uses: actions/checkout@v4
with:
path: ${{ env.PLUGIN_DIR }}

- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
ini-values: -dpcov.enabled=0, pcov.directory=."
extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite, mysql, pdo_mysql
coverage: pcov

- name: add MySQL config file
run: |
mysqldump --version
mysqldump --print-defaults
cp .github/ci-files/.my.cnf ~/.my.cnf
mysqldump --print-defaults

- name: Set SYMFONY_ENV to test
run: |
echo "SYMFONY_ENV=test" >> $GITHUB_ENV
echo "MAUTIC_ENV=test" >> $GITHUB_ENV

- name: Install Composer dependencies
run: |
composer install

# - name: Get composer cache directory
# id: composer-cache
# run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

# - name: Cache composer dependencies
# uses: actions/cache@v4
# with:
# path: ${{ steps.composer-cache.outputs.dir }}
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
# restore-keys: ${{ runner.os }}-composer-

- name: Install Mautic
env:
DB_PORT: ${{ job.services.database.ports[3306] }}
run: |
cp ./.github/ci-files/local.php ./app/config/local.php
php bin/console mautic:install --force http://localhost

- name: Install Plugins
env:
DB_PORT: ${{ job.services.database.ports[3306] }}
run: php bin/console mautic:plugins:install --env=dev

# - name: Run static analysis
# env:
# COMPOSER_ALLOW_SUPERUSER: 1
# run: composer phpstan -- --no-progress

- name: Run Code Style check
run: bin/php-cs-fixer fix ${{ env.PLUGIN_DIR }} --config=.php-cs-fixer.php -v --dry-run --show-progress=dots --diff

# - name: PHPSTAN - baseline (debug, enable if you need to regenerate baseline for all PHP versions)
# run: bin/phpstan --configuration=${{ env.PLUGIN_DIR }}/phpstan.neon --generate-baseline=var/logs/phpstan-baseline-${{ matrix.php-versions }}.neon --allow-empty-baseline

- name: PHPSTAN
run: bin/phpstan --configuration=${{ env.PLUGIN_DIR }}/phpstan.neon

- name: Rector
run: composer rector -- --dry-run --no-progress-bar ${{ env.PLUGIN_DIR }}

- name: Twig Lint
run: bin/console lint:twig ${{ env.PLUGIN_DIR }}

- name: Create writable directory
run: mkdir -p ./media/files/temp && chmod -R 777 ./media/files/temp

- name: Run PHPUNIT tests
env:
DB_PORT: ${{ job.services.database.ports[3306] }}
# run: XDEBUG_MODE=coverage APP_DEBUG=0 php -dpcov.enabled=1 -dpcov.directory=. -dpcov.exclude="~tests|themes|vendor~" bin/phpunit -d memory_limit=1G --bootstrap vendor/autoload.php --configuration ${{ env.PLUGIN_DIR }}/phpunit.xml --coverage-clover=${{ env.PLUGIN_DIR }}/coverage.xml --coverage-text
run: XDEBUG_MODE=coverage APP_DEBUG=0 php -dpcov.enabled=1 -dpcov.directory=. bin/phpunit -d memory_limit=1G --bootstrap vendor/autoload.php --configuration ${{ env.PLUGIN_DIR }}/phpunit.xml --filter=CustomObjectsBundle --coverage-clover=${{ env.PLUGIN_DIR }}/coverage.xml --coverage-text

# - name: Coverage report (debug)
# run: cat ${{ env.PLUGIN_DIR }}/coverage.xml

# - name: Upload coverage report
# if: ${{ matrix.php-versions == '8.0' && matrix.db-types == 'mysql' && matrix.mautic-versions == '4.4' }} # upload just once, change for your matrix
# uses: codecov/codecov-action@v3
# with:
# token: ${{ secrets.CODECOV_TOKEN }}
# fail_ci_if_error: true
# working-directory: ${{ env.PLUGIN_DIR }}
# verbose: true

- name: Upload logs as artifacts
uses: actions/upload-artifact@v4
with:
name: mautic-logs
path: var/logs/
34 changes: 29 additions & 5 deletions Assets/js/custom-objects.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ CustomObjects = {
'id': valueField.attr('id'),
'name': valueField.attr('name'),
'autocomplete': valueField.attr('autocomplete'),
'value': valueField.attr('value')
'value': valueField.val()
};
const fieldType = selectedField.attr('data-field-type');

operatorSelect.empty();

Expand All @@ -67,17 +68,40 @@ CustomObjects = {
newValueField.append(
mQuery("<option></option>")
.attr('value', optionValue)
.attr('selected', valueField.attr('value') == optionValue)
.attr('selected', valueField.val() === optionValue)
.text(options[optionValue])
);
};
}
}

if (fieldType === 'date') {
newValueField.datetimepicker({
timepicker: false,
format: 'Y-m-d',
lazyInit: true,
validateOnBlur: false,
allowBlank: true,
scrollMonth: false,
scrollInput: false,
closeOnDateSelect: true
});
} else if (fieldType === 'datetime') {
newValueField.datetimepicker({
format: 'Y-m-d H:i',
lazyInit: true,
validateOnBlur: false,
allowBlank: true,
scrollMonth: false,
scrollInput: false
});
}

if (isEmptyOperator) {
newValueField.attr('readonly', true);
newValueField.val(null);
newValueField.attr('value', '');
newValueField.attr('disabled', 'disabled');
} else {
newValueField.attr('value', valueFieldAttrs['value']);
newValueField.val(valueField.val());
}

newValueField.attr(valueFieldAttrs);
Expand Down
25 changes: 8 additions & 17 deletions Command/CustomItemsScheduledExportCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

namespace MauticPlugin\CustomObjectsBundle\Command;

use Mautic\CoreBundle\Helper\ExitCode;
use Mautic\CoreBundle\Templating\Helper\FormatterHelper;
use Mautic\CoreBundle\Twig\Helper\FormatterHelper;
use MauticPlugin\CustomObjectsBundle\CustomItemEvents;
use MauticPlugin\CustomObjectsBundle\Event\CustomItemExportSchedulerEvent;
use MauticPlugin\CustomObjectsBundle\Model\CustomItemExportSchedulerModel;
Expand All @@ -19,19 +18,11 @@ class CustomItemsScheduledExportCommand extends Command
{
public const COMMAND_NAME = 'mautic:custom_items:scheduled_export';

private CustomItemExportSchedulerModel $customItemExportSchedulerModel;
private EventDispatcherInterface $eventDispatcher;
private FormatterHelper $formatterHelper;

public function __construct(
CustomItemExportSchedulerModel $customItemExportSchedulerModel,
EventDispatcherInterface $eventDispatcher,
FormatterHelper $formatterHelper
private CustomItemExportSchedulerModel $customItemExportSchedulerModel,
private EventDispatcherInterface $eventDispatcher,
private FormatterHelper $formatterHelper
) {
$this->customItemExportSchedulerModel = $customItemExportSchedulerModel;
$this->eventDispatcher = $eventDispatcher;
$this->formatterHelper = $formatterHelper;

parent::__construct();
}

Expand All @@ -58,14 +49,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int

foreach ($customItemExportSchedulers as $customItemExportScheduler) {
$customItemExportSchedulerEvent = new CustomItemExportSchedulerEvent($customItemExportScheduler);
$this->eventDispatcher->dispatch(CustomItemEvents::CUSTOM_ITEM_PREPARE_EXPORT_FILE, $customItemExportSchedulerEvent);
$this->eventDispatcher->dispatch(CustomItemEvents::CUSTOM_ITEM_MAIL_EXPORT_FILE, $customItemExportSchedulerEvent);
$this->eventDispatcher->dispatch(CustomItemEvents::POST_EXPORT_MAIL_SENT, $customItemExportSchedulerEvent);
$this->eventDispatcher->dispatch($customItemExportSchedulerEvent, CustomItemEvents::CUSTOM_ITEM_PREPARE_EXPORT_FILE);
$this->eventDispatcher->dispatch($customItemExportSchedulerEvent, CustomItemEvents::CUSTOM_ITEM_MAIL_EXPORT_FILE);
$this->eventDispatcher->dispatch($customItemExportSchedulerEvent, CustomItemEvents::POST_EXPORT_MAIL_SENT);
++$count;
}

$output->writeln('CustomItem export email(s) sent: '.$count);

return ExitCode::SUCCESS;
return Command::SUCCESS;
}
}
47 changes: 16 additions & 31 deletions Command/GenerateSampleDataCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,28 @@
namespace MauticPlugin\CustomObjectsBundle\Command;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception;
use Doctrine\ORM\EntityManager;
use MauticPlugin\CustomObjectsBundle\Helper\RandomHelper;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Style\SymfonyStyle;

class GenerateSampleDataCommand extends ContainerAwareCommand
class GenerateSampleDataCommand extends Command
{
/**
* @var EntityManager
*/
private $entityManager;

/**
* @var RandomHelper
*/
private $randomHelper;

/**
* @var Connection
*/
private $connection;
private Connection $connection;

public function __construct(
EntityManager $entityManager,
RandomHelper $randomHelper
private EntityManager $entityManager,
private RandomHelper $randomHelper
) {
parent::__construct();

$this->entityManager = $entityManager;
$this->randomHelper = $randomHelper;
$this->connection = $entityManager->getConnection();
$this->connection = $entityManager->getConnection();
}

/**
Expand Down Expand Up @@ -111,8 +96,6 @@ protected function execute(InputInterface $input, OutputInterface $output)

/**
* @return int[]
*
* @throws DBALException
*/
private function createCustomObjectsWithItems(): array
{
Expand Down Expand Up @@ -150,13 +133,16 @@ private function createCustomObjectsWithItems(): array
return [$coProductId, $cfPriceId, $coOrderId];
}

/**
* @throws Exception
*/
private function cleanupDB(): void
{
$query = 'delete from '.MAUTIC_TABLE_PREFIX.'leads where 1';
$this->connection->query($query);
$this->connection->executeQuery($query);

$query = 'delete from '.MAUTIC_TABLE_PREFIX.'custom_object where 1';
$this->connection->query($query);
$this->connection->executeQuery($query);
}

private function generateContact(int $coProductId, int $cfPriceId, int $coOrderId, int $priceLimit): void
Expand Down Expand Up @@ -220,9 +206,11 @@ private function generateProductRelations(int $contactId, int $coProductId, int
}

/**
* @param array<int|string, mixed> $row
*
* @return int Last inserted row ID
*
* @throws DBALException
* @throws Exception
*/
private function insertInto(string $table, array $row): int
{
Expand All @@ -235,13 +223,10 @@ function ($value) {
switch (gettype($value)) {
case 'string':
return "'$value'";
break;
case 'integer':
return (string) $value;
break;
case 'boolean':
return (bool) $value;
break;
default:
$type = gettype($value);
throw new \InvalidArgumentException("Unsupported type '$type' for insert query");
Expand All @@ -256,7 +241,7 @@ function ($value) {
VALUES ($values)
";

$this->connection->query($query);
$this->connection->executeQuery($query);

return (int) $this->connection->lastInsertId();
}
Expand Down
Loading
Loading