diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 000000000..73fb6088f --- /dev/null +++ b/.github/workflows/tests.yml @@ -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/ diff --git a/Assets/js/custom-objects.js b/Assets/js/custom-objects.js index 705f7104d..92dba61b3 100644 --- a/Assets/js/custom-objects.js +++ b/Assets/js/custom-objects.js @@ -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(); @@ -67,17 +68,40 @@ CustomObjects = { newValueField.append( mQuery("") .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); diff --git a/Command/CustomItemsScheduledExportCommand.php b/Command/CustomItemsScheduledExportCommand.php index 74e4e74a5..3212ccc15 100644 --- a/Command/CustomItemsScheduledExportCommand.php +++ b/Command/CustomItemsScheduledExportCommand.php @@ -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; @@ -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(); } @@ -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; } } diff --git a/Command/GenerateSampleDataCommand.php b/Command/GenerateSampleDataCommand.php index 3ea8458fb..ceb815d44 100644 --- a/Command/GenerateSampleDataCommand.php +++ b/Command/GenerateSampleDataCommand.php @@ -5,10 +5,10 @@ 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; @@ -16,32 +16,17 @@ 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(); } /** @@ -111,8 +96,6 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * @return int[] - * - * @throws DBALException */ private function createCustomObjectsWithItems(): array { @@ -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 @@ -220,9 +206,11 @@ private function generateProductRelations(int $contactId, int $coProductId, int } /** + * @param array $row + * * @return int Last inserted row ID * - * @throws DBALException + * @throws Exception */ private function insertInto(string $table, array $row): int { @@ -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"); @@ -256,7 +241,7 @@ function ($value) { VALUES ($values) "; - $this->connection->query($query); + $this->connection->executeQuery($query); return (int) $this->connection->lastInsertId(); } diff --git a/Config/config.php b/Config/config.php index 1476deaf4..df583a48f 100644 --- a/Config/config.php +++ b/Config/config.php @@ -18,12 +18,12 @@ // Custom Fields CustomFieldRouteProvider::ROUTE_FORM => [ 'path' => '/custom/field/edit', - 'controller' => 'CustomObjectsBundle:CustomField\Form:renderForm', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomField\FormController::renderFormAction', 'method' => 'GET', ], CustomFieldRouteProvider::ROUTE_SAVE => [ 'path' => '/custom/field/save/{fieldType}', - 'controller' => 'CustomObjectsBundle:CustomField\Save:save', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomField\SaveController::saveAction', 'method' => 'POST', 'defaults' => [ 'fieldId' => null, @@ -33,7 +33,7 @@ // Custom Items CustomItemRouteProvider::ROUTE_LIST => [ 'path' => '/custom/object/{objectId}/item/{page}', - 'controller' => 'CustomObjectsBundle:CustomItem\List:list', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ListController::listAction', 'method' => 'GET|POST', 'defaults' => [ 'page' => 1, @@ -41,45 +41,44 @@ ], CustomItemRouteProvider::ROUTE_VIEW => [ 'path' => '/custom/object/{objectId}/item/view/{itemId}', - 'controller' => 'CustomObjectsBundle:CustomItem\View:view', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ViewController::viewAction', 'method' => 'GET|POST', ], CustomItemRouteProvider::ROUTE_NEW => [ 'path' => '/custom/object/{objectId}/item/new', - 'controller' => 'CustomObjectsBundle:CustomItem\Form:new', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\FormController::newAction', 'method' => 'GET', ], CustomItemRouteProvider::ROUTE_NEW_REDIRECT_TO_CONTACT => [ 'path' => '/custom/object/{objectId}/contact/{contactId}/item/new', - 'controller' => 'CustomObjectsBundle:CustomItem\Form:newWithRedirectToContact', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\FormController::newWithRedirectToContactAction', 'method' => 'GET', ], CustomItemRouteProvider::ROUTE_EDIT => [ 'path' => '/custom/object/{objectId}/item/edit/{itemId}', - 'controller' => 'CustomObjectsBundle:CustomItem\Form:edit', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\FormController::editAction', 'method' => 'GET', ], CustomItemRouteProvider::ROUTE_EDIT_REDIRECT_TO_CONTACT => [ 'path' => '/custom/object/{objectId}/item/edit/{itemId}/contact/{contactId}', - 'controller' => 'CustomObjectsBundle:CustomItem\Form:editWithRedirectToContact', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\FormController::editWithRedirectToContactAction', 'method' => 'GET', ], CustomItemRouteProvider::ROUTE_CLONE => [ 'path' => '/custom/object/{objectId}/item/clone/{itemId}', - 'controller' => 'CustomObjectsBundle:CustomItem\Form:clone', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\FormController::cloneAction', 'method' => 'GET', ], CustomItemRouteProvider::ROUTE_CANCEL => [ 'path' => '/custom/object/{objectId}/item/cancel/{itemId}', - 'controller' => 'CustomObjectsBundle:CustomItem\Cancel:cancel', - 'method' => 'POST', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\CancelController::cancelAction', 'defaults' => [ 'itemId' => null, ], ], CustomItemRouteProvider::ROUTE_SAVE => [ 'path' => '/custom/object/{objectId}/item/save/{itemId}', - 'controller' => 'CustomObjectsBundle:CustomItem\Save:save', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\SaveController::saveAction', 'method' => 'POST', 'defaults' => [ 'itemId' => null, @@ -87,57 +86,57 @@ ], CustomItemRouteProvider::ROUTE_DELETE => [ 'path' => '/custom/object/{objectId}/item/delete/{itemId}', - 'controller' => 'CustomObjectsBundle:CustomItem\Delete:delete', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\DeleteController::deleteAction', 'method' => 'GET|POST', ], CustomItemRouteProvider::ROUTE_BATCH_DELETE => [ 'path' => '/custom/object/{objectId}/item/batch/delete', - 'controller' => 'CustomObjectsBundle:CustomItem\BatchDelete:delete', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\BatchDeleteController::deleteAction', 'method' => 'POST', ], CustomItemRouteProvider::ROUTE_LOOKUP => [ 'path' => '/custom/object/{objectId}/item/lookup.json', - 'controller' => 'CustomObjectsBundle:CustomItem\Lookup:list', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\LookupController::listAction', 'method' => 'GET', ], CustomItemRouteProvider::ROUTE_LINK => [ 'path' => '/custom/item/{itemId}/link/{entityType}/{entityId}.json', - 'controller' => 'CustomObjectsBundle:CustomItem\Link:save', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\LinkController::saveAction', 'method' => 'POST', ], CustomItemRouteProvider::ROUTE_LINK_FORM => [ 'path' => '/custom/item/{itemId}/link-form/{entityType}/{entityId}', - 'controller' => 'CustomObjectsBundle:CustomItem\LinkForm:form', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\LinkFormController::formAction', 'method' => 'GET', ], CustomItemRouteProvider::ROUTE_LINK_FORM_SAVE => [ 'path' => '/custom/item/{itemId}/link-form/{entityType}/{entityId}', - 'controller' => 'CustomObjectsBundle:CustomItem\LinkForm:save', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\LinkFormController::saveAction', 'method' => 'POST', ], CustomItemRouteProvider::ROUTE_UNLINK => [ 'path' => '/custom/item/{itemId}/unlink/{entityType}/{entityId}.json', - 'controller' => 'CustomObjectsBundle:CustomItem\Unlink:save', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\UnlinkController::saveAction', 'method' => 'POST', ], CustomItemRouteProvider::ROUTE_CONTACT_LIST => [ 'path' => '/custom/item/{objectId}/contact/{page}', - 'controller' => 'CustomObjectsBundle:CustomItem\ContactList:list', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ContactListController::listAction', ], CustomItemRouteProvider::ROUTE_EXPORT_ACTION => [ 'path' => 'custom/object/{object}/export', - 'controller' => 'CustomObjectsBundle:CustomItem\Export:export', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ExportController::exportAction', 'method' => 'POST', ], CustomItemRouteProvider::ROUTE_EXPORT_DOWNLOAD_ACTION => [ 'path' => '/custom/item/export/download/{fileName}', - 'controller' => 'CustomObjectsBundle:CustomItem\Export:downloadExport', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ExportController::downloadExportAction', ], // Custom Objects CustomObjectRouteProvider::ROUTE_LIST => [ 'path' => '/custom/object/{page}', - 'controller' => 'CustomObjectsBundle:CustomObject\List:list', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomObject\ListController::listAction', 'method' => 'GET|POST', 'defaults' => [ 'page' => 1, @@ -145,35 +144,34 @@ ], CustomObjectRouteProvider::ROUTE_VIEW => [ 'path' => '/custom/object/view/{objectId}', - 'controller' => 'CustomObjectsBundle:CustomObject\View:view', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomObject\ViewController::viewAction', 'method' => 'GET|POST', ], CustomObjectRouteProvider::ROUTE_NEW => [ 'path' => '/custom/object/new', - 'controller' => 'CustomObjectsBundle:CustomObject\Form:new', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomObject\FormController::newAction', 'method' => 'GET', ], CustomObjectRouteProvider::ROUTE_EDIT => [ 'path' => '/custom/object/edit/{objectId}', - 'controller' => 'CustomObjectsBundle:CustomObject\Form:edit', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomObject\FormController::editAction', 'method' => 'GET', ], CustomObjectRouteProvider::ROUTE_CLONE => [ 'path' => '/custom/object/clone/{objectId}', - 'controller' => 'CustomObjectsBundle:CustomObject\Form:clone', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomObject\FormController::cloneAction', 'method' => 'GET', ], CustomObjectRouteProvider::ROUTE_CANCEL => [ 'path' => '/custom/object/cancel/{objectId}', - 'controller' => 'CustomObjectsBundle:CustomObject\Cancel:cancel', - 'method' => 'POST', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomObject\CancelController::cancelAction', 'defaults' => [ 'objectId' => null, ], ], CustomObjectRouteProvider::ROUTE_SAVE => [ 'path' => '/custom/object/save/{objectId}', - 'controller' => 'CustomObjectsBundle:CustomObject\Save:save', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomObject\SaveController::saveAction', 'method' => 'POST', 'defaults' => [ 'objectId' => null, @@ -181,409 +179,126 @@ ], CustomObjectRouteProvider::ROUTE_DELETE => [ 'path' => '/custom/object/delete/{objectId}', - 'controller' => 'CustomObjectsBundle:CustomObject\Delete:delete', + 'controller' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomObject\DeleteController::deleteAction', 'method' => 'GET|POST', ], ], ], 'services' => [ - 'controllers' => [ - // Custom Fields - 'custom_field.form_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomField\FormController::class, - 'arguments' => [ - 'form.factory', - 'mautic.custom.model.field', - 'custom_object.custom_field_factory', - 'custom_field.permission.provider', - 'custom_field.route.provider', - 'mautic.custom.model.object', - 'custom_object.route.provider', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_field.save_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomField\SaveController::class, - 'arguments' => [ - 'form.factory', - 'translator', - 'mautic.custom.model.field', - 'custom_object.custom_field_factory', - 'custom_field.permission.provider', - 'custom_field.route.provider', - 'mautic.custom.model.object', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - - // Custom Items - 'custom_item.list_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ListController::class, - 'arguments' => [ - 'request_stack', - 'custom_object.session.provider_factory', - 'mautic.custom.model.item', - 'mautic.custom.model.object', - 'custom_item.permission.provider', - 'custom_item.route.provider', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.view_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ViewController::class, - 'arguments' => [ - 'request_stack', - 'form.factory', - 'mautic.custom.model.item', - 'mautic.custom.model.import.xref.contact', - 'mautic.core.model.auditlog', - 'custom_item.permission.provider', - 'custom_item.route.provider', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.form_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\FormController::class, - 'arguments' => [ - 'form.factory', - 'mautic.custom.model.object', - 'mautic.custom.model.item', - 'custom_item.permission.provider', - 'custom_item.route.provider', - 'custom_object.lock_flash_message.helper', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.save_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\SaveController::class, - 'arguments' => [ - 'request_stack', - 'form.factory', - 'mautic.core.service.flashbag', - 'mautic.custom.model.item', - 'mautic.custom.model.object', - 'custom_item.permission.provider', - 'custom_item.route.provider', - 'custom_object.lock_flash_message.helper', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.delete_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\DeleteController::class, - 'arguments' => [ - 'mautic.custom.model.item', - 'custom_object.session.provider_factory', - 'mautic.core.service.flashbag', - 'custom_item.permission.provider', - 'custom_item.route.provider', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.batch_delete_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\BatchDeleteController::class, - 'arguments' => [ - 'request_stack', - 'mautic.custom.model.item', - 'custom_object.session.provider_factory', - 'custom_item.permission.provider', - 'custom_item.route.provider', - 'mautic.core.service.flashbag', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.cancel_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\CancelController::class, - 'arguments' => [ - 'custom_object.session.provider_factory', - 'custom_item.route.provider', - 'mautic.custom.model.item', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.lookup_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\LookupController::class, - 'arguments' => [ - 'request_stack', - 'mautic.custom.model.item', - 'custom_item.permission.provider', - 'mautic.core.service.flashbag', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.link_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\LinkController::class, - 'arguments' => [ - 'mautic.custom.model.item', - 'custom_item.permission.provider', - 'mautic.core.service.flashbag', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.link_form_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\LinkFormController::class, - 'arguments' => [ - 'form.factory', - 'mautic.custom.model.item', - 'custom_item.permission.provider', - 'custom_item.route.provider', - 'mautic.core.service.flashbag', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.unlink_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\UnlinkController::class, - 'arguments' => [ - 'mautic.custom.model.item', - 'custom_item.permission.provider', - 'mautic.core.service.flashbag', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.contact_list_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ContactListController::class, - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_item.export_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ExportController::class, - 'arguments' => [ - 'custom_item.permission.provider', - 'mautic.custom.model.export_scheduler', - ], - ], - - // Custom Objects - 'custom_object.list_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomObject\ListController::class, - 'arguments' => [ - 'request_stack', - 'custom_object.session.provider_factory', - 'mautic.custom.model.object', - 'custom_object.permission.provider', - 'custom_object.route.provider', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_object.view_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomObject\ViewController::class, - 'arguments' => [ - 'request_stack', - 'form.factory', - 'mautic.custom.model.object', - 'mautic.core.model.auditlog', - 'custom_object.permission.provider', - 'custom_object.route.provider', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_object.form_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomObject\FormController::class, - 'arguments' => [ - 'form.factory', - 'mautic.custom.model.object', - 'mautic.custom.model.field', - 'custom_object.permission.provider', - 'custom_object.route.provider', - 'custom_field.type.provider', - 'custom_object.lock_flash_message.helper', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_object.save_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomObject\SaveController::class, - 'arguments' => [ - 'request_stack', - 'mautic.core.service.flashbag', - 'form.factory', - 'mautic.custom.model.object', - 'mautic.custom.model.field', - 'custom_object.permission.provider', - 'custom_object.route.provider', - 'custom_field.type.provider', - 'custom_field.field.params.to.string.transformer', - 'custom_field.field.options.to.string.transformer', - 'custom_object.lock_flash_message.helper', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_object.delete_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomObject\DeleteController::class, - 'arguments' => [ - 'mautic.custom.model.object', - 'custom_object.session.provider_factory', - 'mautic.core.service.flashbag', - 'custom_object.permission.provider', - 'event_dispatcher', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - 'custom_object.cancel_controller' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Controller\CustomObject\CancelController::class, - 'arguments' => [ - 'custom_object.session.provider_factory', - 'custom_object.route.provider', - 'mautic.custom.model.object', - ], - 'methodCalls' => [ - 'setContainer' => [ - '@service_container', - ], - ], - ], - ], 'models' => [ 'mautic.custom.model.field' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Model\CustomFieldModel::class, + 'class' => MauticPlugin\CustomObjectsBundle\Model\CustomFieldModel::class, 'arguments' => [ + 'doctrine.orm.entity_manager', + 'mautic.security', + 'event_dispatcher', + 'router', + 'translator', + 'mautic.helper.user', + 'monolog.logger', + 'mautic.helper.core_parameters', 'custom_field.repository', 'custom_field.permission.provider', - 'mautic.helper.user', ], ], 'mautic.custom.model.field.value' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Model\CustomFieldValueModel::class, + 'class' => MauticPlugin\CustomObjectsBundle\Model\CustomFieldValueModel::class, 'arguments' => [ 'doctrine.orm.entity_manager', 'validator', ], ], 'mautic.custom.model.item' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Model\CustomItemModel::class, + 'class' => MauticPlugin\CustomObjectsBundle\Model\CustomItemModel::class, 'arguments' => [ 'doctrine.orm.entity_manager', + 'mautic.security', + 'event_dispatcher', + 'router', + 'translator', + 'mautic.helper.user', + 'monolog.logger', + 'mautic.helper.core_parameters', 'custom_item.repository', 'custom_item.permission.provider', - 'mautic.helper.user', 'mautic.custom.model.field.value', - 'event_dispatcher', 'validator', ], ], 'mautic.custom.model.import.item' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Model\CustomItemImportModel::class, + 'class' => MauticPlugin\CustomObjectsBundle\Model\CustomItemImportModel::class, 'arguments' => [ 'doctrine.orm.entity_manager', + 'mautic.security', + 'event_dispatcher', + 'router', + 'translator', + 'mautic.helper.user', + 'monolog.logger', + 'mautic.helper.core_parameters', 'mautic.custom.model.item', - 'mautic.helper.template.formatter', + 'mautic.helper.twig.formatter', ], ], 'mautic.custom.model.import.xref.contact' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Model\CustomItemXrefContactModel::class, + 'class' => MauticPlugin\CustomObjectsBundle\Model\CustomItemXrefContactModel::class, 'arguments' => [ 'doctrine.orm.entity_manager', + 'mautic.security', + 'event_dispatcher', + 'router', 'translator', + 'mautic.helper.user', + 'monolog.logger', + 'mautic.helper.core_parameters', ], ], 'mautic.custom.model.field.option' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Model\CustomFieldOptionModel::class, + 'class' => MauticPlugin\CustomObjectsBundle\Model\CustomFieldOptionModel::class, 'arguments' => [ 'doctrine.orm.entity_manager', ], ], 'mautic.custom.model.object' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel::class, + 'class' => MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel::class, 'arguments' => [ 'doctrine.orm.entity_manager', + 'mautic.security', + 'event_dispatcher', + 'router', + 'translator', + 'mautic.helper.user', + 'monolog.logger', + 'mautic.helper.core_parameters', 'custom_object.repository', 'custom_object.permission.provider', - 'mautic.helper.user', 'mautic.custom.model.field', - 'event_dispatcher', - 'mautic.lead.model.list', ], ], 'mautic.custom.model.export_scheduler' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Model\CustomItemExportSchedulerModel::class, + 'class' => MauticPlugin\CustomObjectsBundle\Model\CustomItemExportSchedulerModel::class, 'arguments' => [ + 'doctrine.orm.entity_manager', + 'mautic.security', + 'event_dispatcher', + 'router', + 'translator', + 'mautic.helper.user', + 'monolog.logger', + 'mautic.helper.core_parameters', 'mautic.helper.export', 'mautic.helper.mailer', 'mautic.custom.model.field.value', 'custom_item.route.provider', 'custom_item.xref.contact.repository', 'custom_item.repository', - 'event_dispatcher', ], ], ], 'permissions' => [ 'custom_object.permissions' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Security\Permissions\CustomObjectPermissions::class, + 'class' => MauticPlugin\CustomObjectsBundle\Security\Permissions\CustomObjectPermissions::class, 'arguments' => [ 'mautic.helper.core_parameters', 'mautic.custom.model.object', @@ -594,42 +309,42 @@ ], 'repositories' => [ 'custom_field.repository' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Repository\CustomFieldRepository::class, + 'class' => Doctrine\ORM\EntityRepository::class, 'factory' => ['@doctrine.orm.entity_manager', 'getRepository'], 'arguments' => [ - \MauticPlugin\CustomObjectsBundle\Entity\CustomField::class, + MauticPlugin\CustomObjectsBundle\Entity\CustomField::class, ], ], 'custom_item.repository' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository::class, + 'class' => Doctrine\ORM\EntityRepository::class, 'factory' => ['@doctrine.orm.entity_manager', 'getRepository'], 'arguments' => [ - \MauticPlugin\CustomObjectsBundle\Entity\CustomItem::class, + MauticPlugin\CustomObjectsBundle\Entity\CustomItem::class, ], ], 'custom_object.repository' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Repository\CustomObjectRepository::class, + 'class' => Doctrine\ORM\EntityRepository::class, 'factory' => ['@doctrine.orm.entity_manager', 'getRepository'], 'arguments' => [ - \MauticPlugin\CustomObjectsBundle\Entity\CustomObject::class, + MauticPlugin\CustomObjectsBundle\Entity\CustomObject::class, ], ], 'custom_item.xref.contact.repository' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Repository\CustomItemXrefContactRepository::class, + 'class' => Doctrine\ORM\EntityRepository::class, 'factory' => ['@doctrine.orm.entity_manager', 'getRepository'], 'arguments' => [ - \MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefContact::class, + MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefContact::class, ], ], 'custom_item.xref.custom_item.repository' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Repository\CustomItemXrefCustomItemRepository::class, + 'class' => Doctrine\ORM\EntityRepository::class, 'factory' => ['@doctrine.orm.entity_manager', 'getRepository'], 'arguments' => [ - \MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefCustomItem::class, + MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefCustomItem::class, ], ], 'custom_object.segment_decorator_multiselect' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Segment\Decorator\MultiselectDecorator::class, + 'class' => MauticPlugin\CustomObjectsBundle\Segment\Decorator\MultiselectDecorator::class, 'arguments' => [ 'mautic.lead.model.lead_segment_filter_operator', 'mautic.lead.repository.lead_segment_filter_descriptor', @@ -637,51 +352,8 @@ ], ], 'events' => [ - 'custom_object.api.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\ApiSubscriber::class, - 'arguments' => [ - 'custom_object.config.provider', - 'mautic.custom.model.object', - 'mautic.custom.model.item', - ], - ], - 'custom_object.assets.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\AssetsSubscriber::class, - 'arguments' => [ - 'templating.helper.assets', - 'custom_object.config.provider', - ], - ], - 'custom_object.menu.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\MenuSubscriber::class, - 'arguments' => [ - 'mautic.custom.model.object', - 'custom_object.config.provider', - ], - ], - 'custom_object.contact.tab.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\ContactTabSubscriber::class, - 'arguments' => [ - 'mautic.custom.model.object', - 'custom_item.repository', - 'custom_object.config.provider', - 'translator', - 'custom_item.route.provider', - 'custom_object.session.provider_factory', - ], - ], - 'custom_object.custom_item.tab.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomItemTabSubscriber::class, - 'arguments' => [ - 'mautic.custom.model.object', - 'custom_item.repository', - 'translator', - 'custom_item.route.provider', - 'custom_object.session.provider_factory', - ], - ], 'custom_field.post_load.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomFieldPostLoadSubscriber::class, + 'class' => MauticPlugin\CustomObjectsBundle\EventListener\CustomFieldPostLoadSubscriber::class, 'arguments' => [ 'custom_field.type.provider', ], @@ -691,113 +363,16 @@ 'lazy' => true, ], ], - 'custom_object.report.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\ReportSubscriber::class, - 'arguments' => [ - 'custom_object.repository', - 'mautic.lead.reportbundle.fields_builder', - 'mautic.lead.model.company_report_data', - 'mautic.report.helper.report', - 'translator', - ], - ], // There's a problem with multiple tags and arguments definition using array. // So subscriber above should contain subscriber method below. But it is not possible now. 'custom_field.pre_save.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomFieldPreSaveSubscriber::class, + 'class' => MauticPlugin\CustomObjectsBundle\EventListener\CustomFieldPreSaveSubscriber::class, 'arguments' => [ 'mautic.custom.model.field.option', ], ], - 'custom_item.button.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomItemButtonSubscriber::class, - 'arguments' => [ - 'custom_item.permission.provider', - 'custom_item.route.provider', - 'translator', - ], - ], - 'custom_item.xref_contact.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomItemXrefContactSubscriber::class, - 'arguments' => [ - 'doctrine.orm.entity_manager', - 'mautic.helper.user', - 'custom_item.repository', - ], - ], - 'custom_item.export.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomItemScheduledExportSubscriber::class, - 'arguments' => [ - 'mautic.custom.model.export_scheduler', - ], - ], - 'custom_item.xref_item.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomItemXrefCustomItemSubscriber::class, - 'arguments' => [ - 'doctrine.orm.entity_manager', - 'custom_item.repository', - ], - ], - 'custom_item.import.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\ImportSubscriber::class, - 'arguments' => [ - 'mautic.custom.model.object', - 'mautic.custom.model.import.item', - 'custom_object.config.provider', - 'custom_item.permission.provider', - 'custom_field.repository', - 'translator', - ], - ], - 'custom_item.contact.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\ContactSubscriber::class, - 'arguments' => [ - 'doctrine.orm.entity_manager', - 'translator', - 'custom_item.route.provider', - 'mautic.custom.model.item', - 'custom_object.config.provider', - ], - ], - 'custom_item.post_save.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomItemPostSaveSubscriber::class, - 'arguments' => [ - 'mautic.custom.model.item', - 'request_stack', - ], - ], - 'custom_item.post_delete.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomItemPostDeleteSubscriber::class, - 'arguments' => [ - 'custom_item.xref.custom_item.repository', - 'custom_item.xref.contact.repository', - ], - ], - 'custom_object.audit.log.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\AuditLogSubscriber::class, - 'arguments' => [ - 'mautic.core.model.auditlog', - 'mautic.helper.ip_lookup', - ], - ], - 'custom_object.filter.operator.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\FilterOperatorSubscriber::class, - 'arguments' => [ - 'mautic.custom.model.object', - ], - ], - 'custom_object.button.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomObjectButtonSubscriber::class, - 'arguments' => [ - 'custom_object.permission.provider', - 'custom_object.route.provider', - 'custom_item.permission.provider', - 'custom_item.route.provider', - 'translator', - ], - ], 'custom_item.campaign.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CampaignSubscriber::class, + 'class' => MauticPlugin\CustomObjectsBundle\EventListener\CampaignSubscriber::class, 'arguments' => [ 'mautic.custom.model.field', 'mautic.custom.model.object', @@ -809,33 +384,8 @@ 'database_connection', ], ], - 'custom_object.segments.filters_generate.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\SegmentFiltersChoicesGenerateSubscriber::class, - 'arguments'=> [ - 'custom_object.repository', - 'translator', - 'custom_object.config.provider', - 'custom_field.type.provider', - ], - ], - 'custom_object.segments.filters_dictionary.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\SegmentFiltersDictionarySubscriber::class, - 'arguments' => [ - 'doctrine', - 'custom_object.config.provider', - ], - ], - 'custom_object.dynamic_content.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\DynamicContentSubscriber::class, - 'arguments' => [ - 'custom_object.query.filter.factory', - 'custom_object.query.filter.helper', - 'custom_object.config.provider', - 'logger', - ], - ], 'custom_object.serializer.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\SerializerSubscriber::class, + 'class' => MauticPlugin\CustomObjectsBundle\EventListener\SerializerSubscriber::class, 'arguments' => [ 'custom_object.config.provider', 'custom_item.xref.contact.repository', @@ -844,173 +394,100 @@ ], 'tag' => 'jms_serializer.event_subscriber', 'tagArguments' => [ - 'event' => \JMS\Serializer\EventDispatcher\Events::POST_SERIALIZE, + 'event' => JMS\Serializer\EventDispatcher\Events::POST_SERIALIZE, ], ], 'custom_object.emailtoken.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\TokenSubscriber::class, + 'class' => MauticPlugin\CustomObjectsBundle\EventListener\TokenSubscriber::class, 'arguments' => [ 'custom_object.config.provider', 'custom_object.query.filter.helper', 'custom_object.query.filter.factory', 'mautic.custom.model.object', 'mautic.custom.model.item', + 'mautic.custom.model.field', 'custom_object.token.parser', 'mautic.campaign.model.event', 'event_dispatcher', 'custom_object.helper.token_formatter', - ], - ], - 'custom_object.segments.decorator_delegate.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\SegmentFilterDecoratorDelegateSubscriber::class, - 'arguments'=> [ - 'custom_object.segment_decorator_multiselect', - ], - ], - 'custom_object.tokens.list_format.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomObjectListFormatSubscriber::class, - 'arguments' => [ - 'custom_object.helper.token_formatter', - ], - ], - 'custom_object.post_save.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomObjectPostSaveSubscriber::class, - 'arguments' => [ - 'mautic.custom.model.object', - ], - ], - 'custom_object.pre_delete.subscriber' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\EventListener\CustomObjectPreDeleteSubscriber::class, - 'arguments' => [ - 'mautic.custom.model.object', - 'translator', + 'custom_object.helper.filter_evaluator', + '%mautic.custom_item_fetch_limit_per_lead%', ], ], ], 'forms' => [ - 'custom_item.item.form' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Form\Type\CustomItemType::class, - ], - 'custom_field.field.form' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Form\Type\CustomFieldType::class, - 'arguments' => [ - 'custom_object.repository', - 'custom_field.type.provider', - 'custom_field.field.params.to.string.transformer', - 'custom_field.field.options.to.string.transformer', - 'custom_object.custom_field_factory', - ], - 'tag' => 'form.type', - ], 'custom_field.field.params.to.string.transformer' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Form\DataTransformer\ParamsToStringTransformer::class, + 'class' => MauticPlugin\CustomObjectsBundle\Form\DataTransformer\ParamsToStringTransformer::class, 'arguments' => [ 'jms_serializer', ], ], 'custom_field.field.options.to.string.transformer' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Form\DataTransformer\OptionsToStringTransformer::class, + 'class' => MauticPlugin\CustomObjectsBundle\Form\DataTransformer\OptionsToStringTransformer::class, 'arguments' => [ 'jms_serializer', 'mautic.custom.model.field', ], ], - 'custom_object.object.form' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Form\Type\CustomObjectType::class, - 'arguments' => [ - 'doctrine.orm.entity_manager', - 'custom_field.type.provider', - 'custom_object.repository', - ], - 'tag' => 'form.type', - ], - 'custom_field.field.value.form' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Form\Type\CustomFieldValueType::class, - ], - 'custom_item.campaign.link.form' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Form\Type\CampaignActionLinkType::class, - 'arguments' => [ - 'custom_item.route.provider', - 'translator', - ], - ], - 'custom_item.campaign.field.value.form' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Form\Type\CampaignConditionFieldValueType::class, - 'arguments' => [ - 'mautic.custom.model.field', - 'custom_item.route.provider', - 'translator', - ], - ], - ], - 'commands' => [ - 'custom_object.command.generate_sample_data' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Command\GenerateSampleDataCommand::class, - 'arguments' => [ - 'doctrine.orm.entity_manager', - 'custom_object.random.helper', - ], - 'tag' => 'console.command', - ], ], 'fieldTypes' => [ 'custom.field.type.country' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\CountryType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\CountryType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator'], 'tag' => 'custom.field.type', ], 'custom.field.type.date' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\DateType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\DateType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator'], 'tag' => 'custom.field.type', ], 'custom.field.type.datetime' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\DateTimeType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\DateTimeType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator'], 'tag' => 'custom.field.type', ], 'custom.field.type.email' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\EmailType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\EmailType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator'], 'tag' => 'custom.field.type', ], 'custom.field.type.hidden' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\HiddenType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\HiddenType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator'], 'tag' => 'custom.field.type', ], 'custom.field.type.int' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\IntType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\IntType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator'], 'tag' => 'custom.field.type', ], 'custom.field.type.phone' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\PhoneType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\PhoneType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator'], 'tag' => 'custom.field.type', ], 'custom.field.type.select' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\SelectType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\SelectType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator'], 'tag' => 'custom.field.type', ], 'custom.field.type.multiselect' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\MultiselectType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\MultiselectType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator', 'custom_object.csv.helper'], 'tag' => 'custom.field.type', ], 'custom.field.type.text' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\TextType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\TextType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator'], 'tag' => 'custom.field.type', ], 'custom.field.type.textarea' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\TextareaType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\TextareaType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator'], 'tag' => 'custom.field.type', ], 'custom.field.type.url' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\CustomFieldType\UrlType::class, + 'class' => MauticPlugin\CustomObjectsBundle\CustomFieldType\UrlType::class, 'arguments' => ['translator', 'mautic.lead.provider.fillterOperator'], 'tag' => 'custom.field.type', ], @@ -1035,13 +512,13 @@ ], ], 'custom_field.type.provider' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider::class, + 'class' => MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider::class, 'arguments' => [ 'event_dispatcher', ], ], 'custom_field.permission.provider' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Provider\CustomFieldPermissionProvider::class, + 'class' => MauticPlugin\CustomObjectsBundle\Provider\CustomFieldPermissionProvider::class, 'arguments' => [ 'mautic.security', ], @@ -1059,13 +536,13 @@ ], ], 'custom_item.permission.provider' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider::class, + 'class' => MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider::class, 'arguments' => [ 'mautic.security', ], ], 'custom_object.session.provider_factory' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Provider\SessionProviderFactory::class, + 'class' => MauticPlugin\CustomObjectsBundle\Provider\SessionProviderFactory::class, 'arguments' => [ 'session', 'mautic.helper.core_parameters', @@ -1078,13 +555,13 @@ ], ], 'custom_object.permission.provider' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Provider\CustomObjectPermissionProvider::class, + 'class' => MauticPlugin\CustomObjectsBundle\Provider\CustomObjectPermissionProvider::class, 'arguments' => [ 'mautic.security', ], ], 'custom_object.lock_flash_message.helper' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Helper\LockFlashMessageHelper::class, + 'class' => MauticPlugin\CustomObjectsBundle\Helper\LockFlashMessageHelper::class, 'arguments' => [ 'mautic.helper.core_parameters', 'translator', @@ -1093,20 +570,20 @@ ], ], 'custom_object.csv.helper' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Helper\CsvHelper::class, + 'class' => MauticPlugin\CustomObjectsBundle\Helper\CsvHelper::class, ], 'custom_object.token.parser' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Helper\TokenParser::class, + 'class' => MauticPlugin\CustomObjectsBundle\Helper\TokenParser::class, ], 'custom_object.random.helper' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Helper\RandomHelper::class, + 'class' => MauticPlugin\CustomObjectsBundle\Helper\RandomHelper::class, ], 'custom_object.custom_field_factory' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Entity\CustomFieldFactory::class, + 'class' => MauticPlugin\CustomObjectsBundle\Entity\CustomFieldFactory::class, 'arguments' => ['custom_field.type.provider'], ], 'mautic.lead.query.builder.custom_field.value' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\CustomFieldFilterQueryBuilder::class, + 'class' => MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\CustomFieldFilterQueryBuilder::class, 'arguments' => [ 'mautic.lead.model.random_parameter_name', 'event_dispatcher', @@ -1114,25 +591,33 @@ ], ], 'mautic.lead.query.builder.custom_item.value' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\CustomItemNameFilterQueryBuilder::class, + 'class' => MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\CustomItemNameFilterQueryBuilder::class, 'arguments' => [ 'mautic.lead.model.random_parameter_name', 'custom_object.query.filter.helper', 'event_dispatcher', ], ], + 'mautic.lead.query.builder.custom_object.merged.value' => [ + 'class' => MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\CustomObjectMergedFilterQueryBuilder::class, + 'arguments' => [ + 'mautic.lead.model.random_parameter_name', + 'event_dispatcher', + 'custom_object.query.filter.helper', + ], + ], 'custom_object.query.filter.factory' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\QueryFilterFactory::class, + 'class' => MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\QueryFilterFactory::class, 'arguments' => [ 'mautic.lead.model.lead_segment_filter_factory', 'custom_object.query.filter.helper', ], ], 'query_filter_factory_calculator' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Helper\QueryFilterFactory\Calculator::class, + 'class' => MauticPlugin\CustomObjectsBundle\Helper\QueryFilterFactory\Calculator::class, ], 'query_filter_factory' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Helper\QueryFilterFactory::class, + 'class' => MauticPlugin\CustomObjectsBundle\Helper\QueryFilterFactory::class, 'arguments' => [ 'doctrine.orm.entity_manager', 'custom_field.type.provider', @@ -1142,37 +627,53 @@ ], ], 'custom_object.query.filter.helper' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Helper\QueryFilterHelper::class, + 'class' => MauticPlugin\CustomObjectsBundle\Helper\QueryFilterHelper::class, 'arguments' => [ 'doctrine.orm.entity_manager', 'query_filter_factory', + 'mautic.lead.model.random_parameter_name', ], ], 'custom_object.helper.token_formatter' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Helper\TokenFormatter::class, + 'class' => MauticPlugin\CustomObjectsBundle\Helper\TokenFormatter::class, ], - ], - 'validators' => [ - 'custom_object.allow.unique_identifier.validator' => [ - 'class' => \MauticPlugin\CustomObjectsBundle\Form\Validator\Constraints\AllowUniqueIdentifierValidator::class, + 'custom_object.helper.filter_evaluator' => [ + 'class' => MauticPlugin\CustomObjectsBundle\Helper\FilterEvaluator::class, + ], + 'custom_object.helper.contact_filter_matcher' => [ + 'class' => MauticPlugin\CustomObjectsBundle\Helper\ContactFilterMatcher::class, + 'arguments' => [ + 'mautic.custom.model.field', + 'mautic.custom.model.object', + 'mautic.custom.model.item', + 'mautic.lead.repository.company', + 'doctrine.dbal.default_connection', + 'custom_object.helper.filter_evaluator', + '%mautic.custom_item_fetch_limit_per_lead%', + ], + ], + + 'custom_object.data_persister.custom_item' => [ + 'class' => MauticPlugin\CustomObjectsBundle\DataPersister\CustomItemDataPersister::class, + 'tag' => 'api_platform.data_persister', 'arguments' => [ 'mautic.custom.model.item', - 'translator', ], - 'tag' => 'validator.constraint_validator', ], ], ], 'parameters' => [ - ConfigProvider::CONFIG_PARAM_ENABLED => true, - ConfigProvider::CONFIG_PARAM_ITEM_VALUE_TO_CONTACT_RELATION_LIMIT => 3, - 'custom_item_export_dir' => '%kernel.root_dir%/../media/files/temp', + ConfigProvider::CONFIG_PARAM_ENABLED => true, + ConfigProvider::CONFIG_PARAM_ITEM_VALUE_TO_CONTACT_RELATION_LIMIT => ConfigProvider::CONFIG_PARAM_ITEM_VALUE_TO_CONTACT_RELATION_DEFAULT_LIMIT, + 'custom_item_export_dir' => '%kernel.project_dir%/media/files/temp', + 'custom_object_merge_filter' => false, + 'custom_item_fetch_limit_per_lead' => 15, ], ]; if (interface_exists('ApiPlatform\\Core\\Api\\IriConverterInterface')) { $coParams['services']['other']['api_platform.custom_object.serializer.api_normalizer_jsonld'] = [ - 'class' => \MauticPlugin\CustomObjectsBundle\Serializer\ApiNormalizer::class, + 'class' => MauticPlugin\CustomObjectsBundle\Serializer\ApiNormalizer::class, 'decoratedService' => ['api_platform.jsonld.normalizer.item', 'api_platform.jsonld.normalizer.item.inner'], 'arguments' => [ 'api_platform.jsonld.normalizer.item.inner', @@ -1183,7 +684,7 @@ ], ]; $coParams['services']['other']['api_platform.custom_object.serializer.api_normalizer_json'] = [ - 'class' => \MauticPlugin\CustomObjectsBundle\Serializer\ApiNormalizer::class, + 'class' => MauticPlugin\CustomObjectsBundle\Serializer\ApiNormalizer::class, 'decoratedService' => ['api_platform.serializer.normalizer.item', 'api_platform.serializer.normalizer.item.inner'], 'arguments' => [ 'api_platform.serializer.normalizer.item.inner', @@ -1194,7 +695,7 @@ ], ]; $coParams['services']['other']['api_platform.custom_object.custom_item.extension'] = [ - 'class' => \MauticPlugin\CustomObjectsBundle\Extension\CustomItemListeningExtension::class, + 'class' => MauticPlugin\CustomObjectsBundle\Extension\CustomItemListeningExtension::class, 'arguments' => [ 'mautic.helper.user', 'mautic.security', diff --git a/Config/services.php b/Config/services.php new file mode 100644 index 000000000..c513e2f70 --- /dev/null +++ b/Config/services.php @@ -0,0 +1,35 @@ +services() + ->defaults() + ->autowire() + ->autoconfigure() + ->public(); + + $excludes = [ + 'Provider/SessionProvider.php', + 'Report/ReportColumnsBuilder.php', + 'Serializer/ApiNormalizer.php', + 'Extension/CustomItemListeningExtension.php', + // Registered explicitly in config.php so the int $leadCustomItemFetchLimit arg can be set + 'Helper/ContactFilterMatcher.php', + 'Helper/FilterEvaluator.php', + ]; + + $services->load('MauticPlugin\\CustomObjectsBundle\\', '../') + ->exclude('../{'.implode(',', array_merge(MauticCoreExtension::DEFAULT_EXCLUDES, $excludes)).'}'); + + $services->load('MauticPlugin\\CustomObjectsBundle\\Repository\\', '../Repository/*Repository.php'); + + // Aliases so autowiring resolves the config.php-registered services by class name + $services->alias(ContactFilterMatcher::class, 'custom_object.helper.contact_filter_matcher')->public(); + $services->alias(FilterEvaluator::class, 'custom_object.helper.filter_evaluator')->public(); +}; diff --git a/Controller/CustomField/FormController.php b/Controller/CustomField/FormController.php index a2342f093..cc2e8a2cd 100644 --- a/Controller/CustomField/FormController.php +++ b/Controller/CustomField/FormController.php @@ -15,67 +15,21 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldRouteProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectRouteProvider; -use Symfony\Component\Form\FormFactory; -use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\Response; class FormController extends CommonController { - /** - * @var FormFactory - */ - private $formFactory; - - /** - * @var CustomFieldModel - */ - private $customFieldModel; - - /** - * @var CustomFieldPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomFieldRouteProvider - */ - private $fieldRouteProvider; - - /** - * @var CustomFieldFactory - */ - private $customFieldFactory; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomObjectRouteProvider - */ - private $objectRouteProvider; - - public function __construct( - FormFactory $formFactory, + public function renderFormAction( + FormFactoryInterface $formFactory, CustomFieldModel $customFieldModel, CustomFieldFactory $customFieldFactory, CustomFieldPermissionProvider $permissionProvider, CustomFieldRouteProvider $fieldRouteProvider, CustomObjectModel $customObjectModel, CustomObjectRouteProvider $objectRouteProvider - ) { - $this->formFactory = $formFactory; - $this->customFieldModel = $customFieldModel; - $this->customFieldFactory = $customFieldFactory; - $this->permissionProvider = $permissionProvider; - $this->fieldRouteProvider = $fieldRouteProvider; - $this->customObjectModel = $customObjectModel; - $this->objectRouteProvider = $objectRouteProvider; - } - - public function renderFormAction(Request $request): Response - { + ): Response { + $request = $this->getCurrentRequest(); $objectId = (int) $request->get('objectId'); $fieldId = (int) $request->get('fieldId'); $fieldType = $request->get('fieldType'); @@ -83,18 +37,18 @@ public function renderFormAction(Request $request): Response $panelCount = is_numeric($request->get('panelCount')) ? (int) $request->get('panelCount') : null; if ($objectId) { - $customObject = $this->customObjectModel->fetchEntity($objectId); + $customObject = $customObjectModel->fetchEntity($objectId); } else { $customObject = new CustomObject(); } try { if ($fieldId) { - $customField = $this->customFieldModel->fetchEntity($fieldId); - $this->permissionProvider->canEdit($customField); + $customField = $customFieldModel->fetchEntity($fieldId); + $permissionProvider->canEdit($customField); } else { - $this->permissionProvider->canCreate(); - $customField = $this->customFieldFactory->create($fieldType, $customObject); + $permissionProvider->canCreate(); + $customField = $customFieldFactory->create($fieldType, $customObject); } } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); @@ -102,19 +56,19 @@ public function renderFormAction(Request $request): Response return $this->accessDenied(false, $e->getMessage()); } - $route = $this->fieldRouteProvider->buildFormRoute($customField->getId()); - $action = $this->fieldRouteProvider->buildSaveRoute($fieldType, $fieldId, $customObject->getId(), $panelCount, $panelId); - $form = $this->formFactory->create(CustomFieldType::class, $customField, ['action' => $action]); + $route = $fieldRouteProvider->buildFormRoute($customField->getId()); + $action = $fieldRouteProvider->buildSaveRoute($fieldType, $fieldId, $customObject->getId(), $panelCount, $panelId); + $form = $formFactory->create(CustomFieldType::class, $customField, ['action' => $action]); return $this->delegateView( [ - 'returnUrl' => $this->objectRouteProvider->buildEditRoute($customObject->getId()), + 'returnUrl' => $objectRouteProvider->buildEditRoute($customObject->getId()), 'viewParameters' => [ 'customObject' => $customObject, 'customField' => $customField, 'form' => $form->createView(), ], - 'contentTemplate' => 'CustomObjectsBundle:CustomField:form.html.php', + 'contentTemplate' => '@CustomObjects/CustomField/form.html.twig', 'passthroughVars' => [ 'mauticContent' => 'customField', 'route' => $route, diff --git a/Controller/CustomField/SaveController.php b/Controller/CustomField/SaveController.php index 7aff22a2f..7d91b2790 100644 --- a/Controller/CustomField/SaveController.php +++ b/Controller/CustomField/SaveController.php @@ -17,11 +17,10 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldRouteProvider; -use Symfony\Component\Form\FormFactory; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Translation\TranslatorInterface; /** * This controller is not used for saving to database, it is used only to generate forms and data validation. @@ -32,60 +31,20 @@ class SaveController extends CommonController { /** - * @var FormFactory - */ - private $formFactory; - - /** - * @var CustomFieldModel - */ - private $customFieldModel; - - /** - * @var CustomFieldFactory - */ - private $customFieldFactory; - - /** - * @var CustomFieldPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomFieldRouteProvider - */ - private $fieldRouteProvider; - - /** - * @var CustomObjectModel + * Not save but validate Custom Field data and return proper response. Check class description. + * + * @return Response|JsonResponse */ - private $customObjectModel; - - public function __construct( - FormFactory $formFactory, - TranslatorInterface $translator, + public function saveAction( + FormFactoryInterface $formFactory, CustomFieldModel $customFieldModel, CustomFieldFactory $customFieldFactory, CustomFieldPermissionProvider $permissionProvider, CustomFieldRouteProvider $fieldRouteProvider, CustomObjectModel $customObjectModel ) { - $this->formFactory = $formFactory; - $this->translator = $translator; - $this->customFieldModel = $customFieldModel; - $this->customFieldFactory = $customFieldFactory; - $this->permissionProvider = $permissionProvider; - $this->fieldRouteProvider = $fieldRouteProvider; - $this->customObjectModel = $customObjectModel; - } + $request = $this->getCurrentRequest(); - /** - * Not save but validate Custom Field data and return proper response. Check class description. - * - * @return Response|JsonResponse - */ - public function saveAction(Request $request) - { $objectId = (int) $request->get('objectId'); $fieldId = (int) $request->query->get('fieldId'); $fieldType = $request->get('fieldType'); @@ -93,18 +52,18 @@ public function saveAction(Request $request) $panelCount = is_numeric($request->get('panelCount')) ? (int) $request->get('panelCount') : null; if ($objectId) { - $customObject = $this->customObjectModel->fetchEntity($objectId); + $customObject = $customObjectModel->fetchEntity($objectId); } else { $customObject = new CustomObject(); } try { if ($fieldId) { - $customField = $this->customFieldModel->fetchEntity($fieldId); - $this->permissionProvider->canEdit($customField); + $customField = $customFieldModel->fetchEntity($fieldId); + $permissionProvider->canEdit($customField); } else { - $this->permissionProvider->canCreate(); - $customField = $this->customFieldFactory->create($fieldType, $customObject); + $permissionProvider->canCreate(); + $customField = $customFieldFactory->create($fieldType, $customObject); } } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); @@ -114,17 +73,17 @@ public function saveAction(Request $request) $this->recreateOptionsFromPost($request->get('custom_field'), $customField); - $action = $this->fieldRouteProvider->buildSaveRoute($fieldType, $fieldId, $customObject->getId(), $panelCount, $panelId); - $form = $this->formFactory->create(CustomFieldType::class, $customField, ['action' => $action]); + $action = $fieldRouteProvider->buildSaveRoute($fieldType, $fieldId, $customObject->getId(), $panelCount, $panelId); + $form = $formFactory->create(CustomFieldType::class, $customField, ['action' => $action]); $form->handleRequest($request); if ($form->isValid()) { // Render Custom Field form RAT for Custom Object form. - return $this->buildSuccessForm($customObject, $form->getData(), $request); + return $this->buildSuccessForm($customObject, $form->getData(), $request, $customFieldModel, $formFactory); } - $route = $fieldId ? $this->fieldRouteProvider->buildFormRoute($fieldId) : ''; + $route = $fieldId ? $fieldRouteProvider->buildFormRoute($fieldId) : ''; // Render Custom Field form for modal. return $this->delegateView( @@ -134,7 +93,7 @@ public function saveAction(Request $request) 'customField' => $customField, 'form' => $form->createView(), ], - 'contentTemplate' => 'CustomObjectsBundle:CustomField:form.html.php', + 'contentTemplate' => '@CustomObjects/CustomField/form.html.twig', 'passthroughVars' => [ 'mauticContent' => 'customField', 'route' => $route, @@ -147,8 +106,13 @@ public function saveAction(Request $request) /** * Here is CO form panel part build and injected in the frontend as part of existing CO form. */ - private function buildSuccessForm(CustomObject $customObject, CustomField $customField, Request $request): JsonResponse - { + private function buildSuccessForm( + CustomObject $customObject, + CustomField $customField, + Request $request, + CustomFieldModel $customFieldModel, + FormFactoryInterface $formFactory + ): JsonResponse { $panelId = is_numeric($request->get('panelId')) ? (int) $request->get('panelId') : null; // Is edit of existing panel in view if (null === $panelId) { @@ -167,18 +131,18 @@ private function buildSuccessForm(CustomObject $customObject, CustomField $custo $option->setCustomField($customField); } - $this->customFieldModel->setAlias($customField); + $customFieldModel->setAlias($customField); $customFields = new ArrayCollection([$customField]); $customObject->setCustomFields($customFields); - $form = $this->formFactory->create( + $form = $formFactory->create( CustomObjectType::class, $customObject ); $template = $this->render( - 'CustomObjectsBundle:CustomObject:_form-fields.html.php', + '@CustomObjects/CustomObject/_form-fields.html.twig', [ 'form' => $form->createView(), 'panelId' => $panelId, // Panel id to me replaced if edit @@ -212,7 +176,7 @@ private function buildSuccessForm(CustomObject $customObject, CustomField $custo * * @see \Symfony\Component\Form\Exception\TransformationFailedException * - * @param string[] $customFieldPost + * @param mixed[] $customFieldPost */ private function recreateOptionsFromPost(array $customFieldPost, CustomField $customField): void { diff --git a/Controller/CustomItem/BatchDeleteController.php b/Controller/CustomItem/BatchDeleteController.php index aacfc6306..f4b41e0ca 100644 --- a/Controller/CustomItem/BatchDeleteController.php +++ b/Controller/CustomItem/BatchDeleteController.php @@ -12,88 +12,48 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; use MauticPlugin\CustomObjectsBundle\Provider\SessionProviderFactory; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; class BatchDeleteController extends CommonController { - /** - * @var RequestStack - */ - private $requestStack; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var SessionProviderFactory - */ - private $sessionProviderFactory; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomItemRouteProvider - */ - private $routeProvider; - - /** - * @var FlashBag - */ - private $flashBag; - - public function __construct( - RequestStack $requestStack, + public function deleteAction( CustomItemModel $customItemModel, SessionProviderFactory $sessionProviderFactory, CustomItemPermissionProvider $permissionProvider, CustomItemRouteProvider $routeProvider, - FlashBag $flashBag - ) { - $this->requestStack = $requestStack; - $this->customItemModel = $customItemModel; - $this->sessionProviderFactory = $sessionProviderFactory; - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - $this->flashBag = $flashBag; - } + FlashBag $flashBag, + int $objectId + ): Response { + $request = $this->getCurrentRequest(); - public function deleteAction(int $objectId): Response - { - $request = $this->requestStack->getCurrentRequest(); $itemIds = json_decode($request->get('ids', '[]'), true); - $page = $this->sessionProviderFactory->createItemProvider($objectId)->getPage(); + $page = $sessionProviderFactory->createItemProvider($objectId)->getPage(); $notFound = []; $denied = []; $deleted = []; foreach ($itemIds as $itemId) { try { - $customItem = $this->customItemModel->fetchEntity((int) $itemId); - $this->permissionProvider->canDelete($customItem); - $this->customItemModel->delete($customItem); + $customItem = $customItemModel->fetchEntity((int) $itemId); + $permissionProvider->canDelete($customItem); + $customItemModel->delete($customItem); $deleted[] = $itemId; - } catch (NotFoundException $e) { + } catch (NotFoundException) { $notFound[] = $itemId; - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { $denied[] = $itemId; } } if ($deleted) { - $this->flashBag->add( + $flashBag->add( 'mautic.core.notice.batch_deleted', ['%count%' => count($deleted)] ); } if ($notFound) { - $this->flashBag->add( + $flashBag->add( 'custom.item.error.items.not.found', ['%ids%' => implode(',', $notFound)], FlashBag::LEVEL_ERROR @@ -101,7 +61,7 @@ public function deleteAction(int $objectId): Response } if ($denied) { - $this->flashBag->add( + $flashBag->add( 'custom.item.error.items.denied', ['%ids%' => implode(',', $denied)], FlashBag::LEVEL_ERROR @@ -110,9 +70,9 @@ public function deleteAction(int $objectId): Response return $this->postActionRedirect( [ - 'returnUrl' => $this->routeProvider->buildListRoute($objectId, $page), + 'returnUrl' => $routeProvider->buildListRoute($objectId, $page), 'viewParameters' => ['objectId' => $objectId, 'page' => $page], - 'contentTemplate' => 'CustomObjectsBundle:CustomItem\List:list', + 'contentTemplate' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ListController::listAction', 'passthroughVars' => [ 'mauticContent' => 'customItem', ], diff --git a/Controller/CustomItem/CancelController.php b/Controller/CustomItem/CancelController.php index 7179f1f07..49e211e38 100644 --- a/Controller/CustomItem/CancelController.php +++ b/Controller/CustomItem/CancelController.php @@ -14,47 +14,27 @@ class CancelController extends CommonController { /** - * @var SessionProviderFactory - */ - private $sessionProviderFactory; - - /** - * @var CustomItemRouteProvider - */ - private $routeProvider; - - /** - * @var CustomItemModel + * @throws NotFoundException */ - private $customItemModel; - - public function __construct( + public function cancelAction( SessionProviderFactory $sessionProviderFactory, CustomItemRouteProvider $routeProvider, - CustomItemModel $customItemModel - ) { - $this->sessionProviderFactory = $sessionProviderFactory; - $this->routeProvider = $routeProvider; - $this->customItemModel = $customItemModel; - } - - /** - * @throws NotFoundException - */ - public function cancelAction(int $objectId, ?int $itemId = null): Response - { - $page = $this->sessionProviderFactory->createItemProvider($objectId)->getPage(); + CustomItemModel $customItemModel, + int $objectId, + ?int $itemId = null + ): Response { + $page = $sessionProviderFactory->createItemProvider($objectId)->getPage(); if ($itemId) { - $customItem = $this->customItemModel->fetchEntity($itemId); - $this->customItemModel->unlockEntity($customItem); + $customItem = $customItemModel->fetchEntity($itemId); + $customItemModel->unlockEntity($customItem); } return $this->postActionRedirect( [ - 'returnUrl' => $this->routeProvider->buildListRoute($objectId, $page), + 'returnUrl' => $routeProvider->buildListRoute($objectId, $page), 'viewParameters' => ['objectId' => $objectId, 'page' => $page], - 'contentTemplate' => 'CustomObjectsBundle:CustomItem\List:list', + 'contentTemplate' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ListController::listAction', 'passthroughVars' => [ 'mauticContent' => 'customItem', ], diff --git a/Controller/CustomItem/ContactListController.php b/Controller/CustomItem/ContactListController.php index cc6a4edf3..a1af5def4 100644 --- a/Controller/CustomItem/ContactListController.php +++ b/Controller/CustomItem/ContactListController.php @@ -5,7 +5,9 @@ namespace MauticPlugin\CustomObjectsBundle\Controller\CustomItem; use Mautic\CoreBundle\Controller\CommonController; +use Mautic\CoreBundle\Factory\PageHelperFactoryInterface; use Mautic\LeadBundle\Controller\EntityContactsTrait; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class ContactListController extends CommonController @@ -15,9 +17,15 @@ class ContactListController extends CommonController /** * @codeCoverageIgnore as this just calls a Mautic core method */ - public function listAction(int $objectId, int $page = 1): Response - { + public function listAction( + Request $request, + PageHelperFactoryInterface $pageHelperFactory, + int $objectId, + int $page = 1 + ): Response { return $this->generateContactsGrid( + $request, + $pageHelperFactory, $objectId, $page, 'lead:lists:viewother', diff --git a/Controller/CustomItem/DeleteController.php b/Controller/CustomItem/DeleteController.php index cb9e4c578..651f86abf 100644 --- a/Controller/CustomItem/DeleteController.php +++ b/Controller/CustomItem/DeleteController.php @@ -16,59 +16,27 @@ class DeleteController extends CommonController { - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var SessionProviderFactory - */ - private $sessionProviderFactory; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomItemRouteProvider - */ - private $routeProvider; - - /** - * @var FlashBag - */ - private $flashBag; - - public function __construct( + public function deleteAction( CustomItemModel $customItemModel, SessionProviderFactory $sessionProviderFactory, FlashBag $flashBag, CustomItemPermissionProvider $permissionProvider, - CustomItemRouteProvider $routeProvider - ) { - $this->customItemModel = $customItemModel; - $this->sessionProviderFactory = $sessionProviderFactory; - $this->flashBag = $flashBag; - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - } - - public function deleteAction(int $objectId, int $itemId): Response - { + CustomItemRouteProvider $routeProvider, + int $objectId, + int $itemId + ): Response { try { - $customItem = $this->customItemModel->fetchEntity($itemId); - $this->permissionProvider->canDelete($customItem); + $customItem = $customItemModel->fetchEntity($itemId); + $permissionProvider->canDelete($customItem); } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } - $this->customItemModel->delete($customItem); + $customItemModel->delete($customItem); - $this->flashBag->add( + $flashBag->add( 'mautic.core.notice.deleted', [ '%name%' => $customItem->getName(), @@ -76,14 +44,13 @@ public function deleteAction(int $objectId, int $itemId): Response ] ); - $page = $this->sessionProviderFactory->createItemProvider($objectId) - ->getPage(); + $page = $sessionProviderFactory->createItemProvider($objectId)->getPage(); return $this->postActionRedirect( [ - 'returnUrl' => $this->routeProvider->buildListRoute($objectId, $page), + 'returnUrl' => $routeProvider->buildListRoute($objectId, $page), 'viewParameters' => ['objectId' => $objectId, 'page' => $page], - 'contentTemplate' => 'CustomObjectsBundle:CustomItem\List:list', + 'contentTemplate' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ListController::listAction', 'passthroughVars' => [ 'mauticContent' => 'customItem', ], diff --git a/Controller/CustomItem/ExportController.php b/Controller/CustomItem/ExportController.php index 52a9c1979..0f9a1b05e 100644 --- a/Controller/CustomItem/ExportController.php +++ b/Controller/CustomItem/ExportController.php @@ -4,60 +4,54 @@ namespace MauticPlugin\CustomObjectsBundle\Controller\CustomItem; +use Doctrine\ORM\OptimisticLockException; +use Doctrine\ORM\ORMException; use Mautic\CoreBundle\Controller\AbstractFormController; use MauticPlugin\CustomObjectsBundle\CustomItemEvents; use MauticPlugin\CustomObjectsBundle\Event\CustomItemExportSchedulerEvent; +use MauticPlugin\CustomObjectsBundle\Exception\ForbiddenException; use MauticPlugin\CustomObjectsBundle\Model\CustomItemExportSchedulerModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; class ExportController extends AbstractFormController { - private CustomItemPermissionProvider $permissionProvider; - - private CustomItemExportSchedulerModel $model; - - public function __construct( - CustomItemPermissionProvider $permissionProvider, - CustomItemExportSchedulerModel $model - ) { - $this->permissionProvider = $permissionProvider; - $this->model = $model; - } - /** - * @throws \Doctrine\ORM\ORMException - * @throws \Doctrine\ORM\OptimisticLockException - * @throws \MauticPlugin\CustomObjectsBundle\Exception\ForbiddenException + * @throws ORMException + * @throws OptimisticLockException + * @throws ForbiddenException */ - public function exportAction(int $object): Response - { - $this->permissionProvider->canCreate($object); + public function exportAction( + CustomItemPermissionProvider $permissionProvider, + CustomItemExportSchedulerModel $model, + int $object + ): Response { + $permissionProvider->canCreate($object); - $customItemExportScheduler = $this->model->saveEntity($object); + $customItemExportScheduler = $model->saveEntity($object); - /** @var EventDispatcherInterface $dispatcher */ - $dispatcher = $this->get('event_dispatcher'); - $dispatcher->dispatch( - CustomItemEvents::ON_CUSTOM_ITEM_SCHEDULE_EXPORT, - new CustomItemExportSchedulerEvent($customItemExportScheduler) + $this->dispatcher->dispatch( + new CustomItemExportSchedulerEvent($customItemExportScheduler), + CustomItemEvents::ON_CUSTOM_ITEM_SCHEDULE_EXPORT ); - $this->addFlash('custom.item.export.being.prepared', ['%user_email%' => $this->user->getEmail()]); + $this->addFlashMessage( + 'custom.item.export.being.prepared', + ['%user_email%' => $this->user->getEmail()] + ); $response['message'] = 'Custom Item export scheduled.'; $response['flashes'] = $this->getFlashContent(); return new JsonResponse($response); } - public function downloadExportAction(string $fileName): Response + public function downloadExportAction(CustomItemExportSchedulerModel $model, string $fileName): Response { try { - return $this->model->getExportFileToDownload($fileName); - } catch (FileNotFoundException $exception) { + return $model->getExportFileToDownload($fileName); + } catch (FileNotFoundException) { return $this->notFound(); } } diff --git a/Controller/CustomItem/FormController.php b/Controller/CustomItem/FormController.php index 5be8c013e..74873f61b 100644 --- a/Controller/CustomItem/FormController.php +++ b/Controller/CustomItem/FormController.php @@ -14,171 +14,177 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; -use Symfony\Component\Form\FormFactory; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\Response; class FormController extends AbstractFormController { - /** - * @var FormFactory - */ - private $formFactory; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomItemRouteProvider - */ - private $routeProvider; - - /** - * @var LockFlashMessageHelper - */ - private $lockFlashMessageHelper; - - public function __construct( - FormFactory $formFactory, - CustomObjectModel $customObjectModel, + public function newAction( + FormFactoryInterface $formFactory, + CustomItemRouteProvider $routeProvider, CustomItemModel $customItemModel, + CustomObjectModel $customObjectModel, CustomItemPermissionProvider $permissionProvider, - CustomItemRouteProvider $routeProvider, - LockFlashMessageHelper $lockFlashMessageHelper - ) { - $this->formFactory = $formFactory; - $this->customObjectModel = $customObjectModel; - $this->customItemModel = $customItemModel; - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - $this->lockFlashMessageHelper = $lockFlashMessageHelper; - } - - public function newAction(int $objectId): Response - { + int $objectId + ): Response { try { - $customItem = $this->performNewAction($objectId); + $customItem = $this->performNewAction($customObjectModel, $customItemModel, $permissionProvider, $objectId); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } - return $this->renderFormForItem($customItem, $this->routeProvider->buildNewRoute($objectId)); + return $this->renderFormForItem( + $formFactory, + $routeProvider, + $customItem, + $routeProvider->buildNewRoute($objectId) + ); } - public function newWithRedirectToContactAction(int $objectId, int $contactId): Response - { + public function newWithRedirectToContactAction( + FormFactoryInterface $formFactory, + CustomItemRouteProvider $routeProvider, + CustomItemModel $customItemModel, + CustomObjectModel $customObjectModel, + CustomItemPermissionProvider $permissionProvider, + int $objectId, + int $contactId + ): Response { try { - $customItem = $this->performNewAction($objectId); + $customItem = $this->performNewAction($customObjectModel, $customItemModel, $permissionProvider, $objectId); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } if ($customItem->getCustomObject()->getRelationshipObject()) { $customItem->setChildCustomItem( - $this->customItemModel->populateCustomFields( + $customItemModel->populateCustomFields( new CustomItem($customItem->getCustomObject()->getRelationshipObject()) ) ); } - return $this->renderFormForItem($customItem, $this->routeProvider->buildNewRouteWithRedirectToContact($objectId, $contactId), $contactId); + return $this->renderFormForItem( + $formFactory, + $routeProvider, + $customItem, + $routeProvider->buildNewRouteWithRedirectToContact($objectId, $contactId), + $contactId + ); } - private function performNewAction(int $objectId): CustomItem - { - $this->permissionProvider->canCreate($objectId); + private function performNewAction( + CustomObjectModel $customObjectModel, + CustomItemModel $customItemModel, + CustomItemPermissionProvider $permissionProvider, + int $objectId + ): CustomItem { + $permissionProvider->canCreate($objectId); - return $this->customItemModel->populateCustomFields( + return $customItemModel->populateCustomFields( new CustomItem( - $this->customObjectModel->fetchEntity($objectId) + $customObjectModel->fetchEntity($objectId) ) ); } - public function editAction(int $objectId, int $itemId): Response - { + public function editAction( + FormFactoryInterface $formFactory, + CustomItemRouteProvider $routeProvider, + CustomItemModel $customItemModel, + LockFlashMessageHelper $lockFlashMessageHelper, + CustomItemPermissionProvider $permissionProvider, + int $objectId, + int $itemId + ): Response { try { - $customItem = $this->performEditAction($itemId); + $customItem = $this->performEditAction($customItemModel, $permissionProvider, $itemId); } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } - if ($this->customItemModel->isLocked($customItem)) { - $this->lockFlashMessageHelper->addFlash( + if ($customItemModel->isLocked($customItem)) { + $lockFlashMessageHelper->addFlash( $customItem, - $this->routeProvider->buildEditRoute($objectId, $itemId), + $routeProvider->buildEditRoute($objectId, $itemId), $this->canEdit($customItem), 'custom.item' ); - return $this->redirect($this->routeProvider->buildViewRoute($objectId, $itemId)); + return $this->redirect($routeProvider->buildViewRoute($objectId, $itemId)); } - $this->customItemModel->lockEntity($customItem); + $customItemModel->lockEntity($customItem); - return $this->renderFormForItem($customItem, $this->routeProvider->buildEditRoute($objectId, $itemId)); + return $this->renderFormForItem( + $formFactory, + $routeProvider, + $customItem, + $routeProvider->buildEditRoute($objectId, $itemId) + ); } - public function editWithRedirectToContactAction(int $objectId, int $itemId, int $contactId): Response - { + public function editWithRedirectToContactAction( + FormFactoryInterface $formFactory, + CustomItemRouteProvider $routeProvider, + CustomItemModel $customItemModel, + LockFlashMessageHelper $lockFlashMessageHelper, + CustomItemPermissionProvider $permissionProvider, + int $objectId, + int $itemId, + int $contactId + ): Response { try { - $customItem = $this->performEditAction($itemId); + $customItem = $this->performEditAction($customItemModel, $permissionProvider, $itemId); } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } - if ($this->customItemModel->isLocked($customItem)) { - $this->lockFlashMessageHelper->addFlash( + if ($customItemModel->isLocked($customItem)) { + $lockFlashMessageHelper->addFlash( $customItem, - $this->routeProvider->buildEditRouteWithRedirectToContact($objectId, $itemId, $contactId), + $routeProvider->buildEditRouteWithRedirectToContact($objectId, $itemId, $contactId), $this->canEdit($customItem), 'custom.item' ); - return $this->redirect($this->routeProvider->buildViewRoute($objectId, $itemId)); + return $this->redirect($routeProvider->buildViewRoute($objectId, $itemId)); } if ($customItem->getCustomObject()->getRelationshipObject()) { $customItem->setChildCustomItem( - $this->customItemModel->populateCustomFields( + $customItemModel->populateCustomFields( $customItem->findChildCustomItem() ) ); } - $this->customItemModel->lockEntity($customItem); - - return $this->renderFormForItem($customItem, $this->routeProvider->buildEditRouteWithRedirectToContact($objectId, $itemId, $contactId), $contactId); - } - - private function performEditAction(int $itemId): CustomItem - { - $customItem = $this->customItemModel->fetchEntity($itemId); - $this->permissionProvider->canEdit($customItem); + $customItemModel->lockEntity($customItem); - return $customItem; + return $this->renderFormForItem( + $formFactory, + $routeProvider, + $customItem, + $routeProvider->buildEditRouteWithRedirectToContact($objectId, $itemId, $contactId), + $contactId + ); } - public function cloneAction(int $objectId, int $itemId): Response - { + public function cloneAction( + FormFactoryInterface $formFactory, + CustomItemRouteProvider $routeProvider, + CustomItemModel $customItemModel, + CustomItemPermissionProvider $permissionProvider, + int $objectId, + int $itemId + ): Response { try { - $customItem = clone $this->customItemModel->fetchEntity($itemId); - $this->permissionProvider->canClone($customItem); + $customItem = clone $customItemModel->fetchEntity($itemId); + $permissionProvider->canClone($customItem); } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); } catch (ForbiddenException $e) { @@ -187,20 +193,41 @@ public function cloneAction(int $objectId, int $itemId): Response $customItem->setName($customItem->getName().' '.$this->translator->trans('mautic.core.form.clone')); - return $this->renderFormForItem($customItem, $this->routeProvider->buildCloneRoute($objectId, $itemId)); + return $this->renderFormForItem( + $formFactory, + $routeProvider, + $customItem, + $routeProvider->buildCloneRoute($objectId, $itemId) + ); + } + + private function performEditAction( + CustomItemModel $customItemModel, + CustomItemPermissionProvider $permissionProvider, + int $itemId + ): CustomItem { + $customItem = $customItemModel->fetchEntity($itemId); + $permissionProvider->canEdit($customItem); + + return $customItem; } - private function renderFormForItem(CustomItem $customItem, string $route, ?int $contactId = null): Response - { - $action = $this->routeProvider->buildSaveRoute($customItem->getCustomObject()->getId(), $customItem->getId()); + private function renderFormForItem( + FormFactoryInterface $formFactory, + CustomItemRouteProvider $routeProvider, + CustomItem $customItem, + string $route, + ?int $contactId = null + ): Response { + $action = $routeProvider->buildSaveRoute($customItem->getCustomObject()->getId(), $customItem->getId()); $options = [ 'action' => $action, 'objectId' => $customItem->getCustomObject()->getId(), 'contactId' => $contactId, - 'cancelUrl' => 0 < $contactId ? $this->routeProvider->buildContactViewRoute($contactId) : null, + 'cancelUrl' => 0 < $contactId ? $routeProvider->buildContactViewRoute($contactId) : null, ]; - $form = $this->formFactory->create( + $form = $formFactory->create( CustomItemType::class, $customItem, $options @@ -208,13 +235,13 @@ private function renderFormForItem(CustomItem $customItem, string $route, ?int $ return $this->delegateView( [ - 'returnUrl' => $this->routeProvider->buildListRoute($customItem->getCustomObject()->getId()), + 'returnUrl' => $routeProvider->buildListRoute($customItem->getCustomObject()->getId()), 'viewParameters' => [ 'entity' => $customItem, 'customObject' => $customItem->getCustomObject(), 'form' => $form->createView(), ], - 'contentTemplate' => 'CustomObjectsBundle:CustomItem:form.html.php', + 'contentTemplate' => '@CustomObjects/CustomItem/form.html.twig', 'passthroughVars' => [ 'mauticContent' => 'customItem', 'route' => $route, diff --git a/Controller/CustomItem/LinkController.php b/Controller/CustomItem/LinkController.php index fcf3192b9..6b4e33607 100644 --- a/Controller/CustomItem/LinkController.php +++ b/Controller/CustomItem/LinkController.php @@ -12,56 +12,36 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use Symfony\Component\HttpFoundation\JsonResponse; -use UnexpectedValueException; class LinkController extends JsonController { - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var FlashBag - */ - private $flashBag; - - public function __construct( + public function saveAction( CustomItemModel $customItemModel, CustomItemPermissionProvider $permissionProvider, - FlashBag $flashBag - ) { - $this->customItemModel = $customItemModel; - $this->permissionProvider = $permissionProvider; - $this->flashBag = $flashBag; - } - - public function saveAction(int $itemId, string $entityType, int $entityId): JsonResponse - { + FlashBag $flashBag, + int $itemId, + string $entityType, + int $entityId + ): JsonResponse { try { - $customItem = $this->customItemModel->fetchEntity($itemId); + $customItem = $customItemModel->fetchEntity($itemId); - $this->permissionProvider->canEdit($customItem); + $permissionProvider->canEdit($customItem); - $this->customItemModel->linkEntity($customItem, $entityType, $entityId); + $customItemModel->linkEntity($customItem, $entityType, $entityId); - $this->flashBag->add( + $flashBag->add( 'custom.item.linked', ['%itemId%' => $customItem->getId(), '%itemName%' => $customItem->getName(), '%entityType%' => $entityType, '%entityId%' => $entityId] ); - } catch (UniqueConstraintViolationException $e) { - $this->flashBag->add( + } catch (UniqueConstraintViolationException) { + $flashBag->add( 'custom.item.error.link.exists.already', ['%itemId%' => $itemId, '%entityType%' => $entityType, '%entityId%' => $entityId], FlashBag::LEVEL_ERROR ); - } catch (ForbiddenException|NotFoundException|UnexpectedValueException $e) { - $this->flashBag->add($e->getMessage(), [], FlashBag::LEVEL_ERROR); + } catch (ForbiddenException|NotFoundException|\UnexpectedValueException $e) { + $flashBag->add($e->getMessage(), [], FlashBag::LEVEL_ERROR); } return $this->renderJson(); diff --git a/Controller/CustomItem/LinkFormController.php b/Controller/CustomItem/LinkFormController.php index 763778af4..0e1cb6a3a 100644 --- a/Controller/CustomItem/LinkFormController.php +++ b/Controller/CustomItem/LinkFormController.php @@ -16,71 +16,40 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; -use Symfony\Component\Form\FormFactory; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use UnexpectedValueException; class LinkFormController extends AbstractFormController { - /** - * @var FormFactory - */ - private $formFactory; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var FlashBag - */ - private $flashBag; - - /** - * @var CustomItemRouteProvider - */ - private $routeProvider; - - public function __construct( - FormFactory $formFactory, + public function formAction( + FormFactoryInterface $formFactory, CustomItemModel $customItemModel, CustomItemPermissionProvider $permissionProvider, CustomItemRouteProvider $customItemRouteProvider, - FlashBag $flashBag - ) { - $this->formFactory = $formFactory; - $this->customItemModel = $customItemModel; - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $customItemRouteProvider; - $this->flashBag = $flashBag; - } - - public function formAction(int $itemId, string $entityType, int $entityId): Response - { + FlashBag $flashBag, + int $itemId, + string $entityType, + int $entityId + ): Response { try { - $customItem = $this->customItemModel->fetchEntity($itemId); + $customItem = $customItemModel->fetchEntity($itemId); if (null === $relationshipObject = $customItem->getCustomObject()->getRelationshipObject()) { throw new NoRelationshipException(); } - $this->permissionProvider->canEdit($customItem); + $permissionProvider->canEdit($customItem); - $relationshipItem = $this->getRelationshipItem($relationshipObject, $customItem, $entityType, $entityId); + $relationshipItem = $this->getRelationshipItem($customItemModel, $relationshipObject, $customItem, $entityType, $entityId); $relationshipItem->generateNameForChildObject($entityType, $entityId, $customItem); - $form = $this->formFactory->create( + $form = $formFactory->create( CustomItemType::class, $relationshipItem, [ - 'action' => $this->routeProvider->buildLinkFormSaveRoute($customItem->getId(), $entityType, $entityId), + 'action' => $customItemRouteProvider->buildLinkFormSaveRoute($customItem->getId(), $entityType, $entityId), 'objectId' => $relationshipObject->getId(), 'contactId' => $entityId, 'cancelUrl' => '', @@ -89,112 +58,126 @@ public function formAction(int $itemId, string $entityType, int $entityId): Resp return $this->delegateView( [ - 'returnUrl' => $this->routeProvider->buildContactViewRoute($entityId), + 'returnUrl' => $customItemRouteProvider->buildContactViewRoute($entityId), 'viewParameters' => [ 'entity' => $relationshipItem, 'customObject' => $relationshipObject, 'form' => $form->createView(), ], - 'contentTemplate' => 'CustomObjectsBundle:CustomItem:form.html.php', + 'contentTemplate' => '@CustomObjects/CustomItem/form.html.twig', 'passthroughVars' => [ 'callback' => 'customItemLinkFormLoad', 'mauticContent' => 'customItem', - 'route' => $this->routeProvider->buildNewRoute($relationshipObject->getId()), + 'route' => $customItemRouteProvider->buildNewRoute($relationshipObject->getId()), ], ] ); - } catch (ForbiddenException|NotFoundException|UnexpectedValueException|NoRelationshipException $e) { - $this->flashBag->add($e->getMessage(), [], FlashBag::LEVEL_ERROR); + } catch (ForbiddenException|NotFoundException|\UnexpectedValueException|NoRelationshipException $e) { + $flashBag->add($e->getMessage(), [], FlashBag::LEVEL_ERROR); } $responseData = [ 'closeModal' => true, - 'flashes' => $this->renderView('MauticCoreBundle:Notification:flash_messages.html.php'), + 'flashes' => $this->renderView('@MauticCore/Notification/flash_messages.html.twig'), ]; return new JsonResponse($responseData); } - public function saveAction(int $itemId, string $entityType, int $entityId): Response - { + public function saveAction( + Request $request, + FormFactoryInterface $formFactory, + CustomItemModel $customItemModel, + CustomItemPermissionProvider $permissionProvider, + CustomItemRouteProvider $customItemRouteProvider, + FlashBag $flashBag, + int $itemId, + string $entityType, + int $entityId + ): Response { $relationshipItem = null; $relationshipObject = null; $form = null; try { - $customItem = $this->customItemModel->fetchEntity($itemId); + $customItem = $customItemModel->fetchEntity($itemId); if (null === $relationshipObject = $customItem->getCustomObject()->getRelationshipObject()) { throw new NoRelationshipException(); } - $this->permissionProvider->canCreate($relationshipObject->getId()); + $permissionProvider->canCreate($relationshipObject->getId()); - $relationshipItem = $this->getRelationshipItem($relationshipObject, $customItem, $entityType, $entityId); + $relationshipItem = $this->getRelationshipItem($customItemModel, $relationshipObject, $customItem, $entityType, $entityId); $relationshipItem->generateNameForChildObject($entityType, $entityId, $customItem); - $form = $this->formFactory->create( + $form = $formFactory->create( CustomItemType::class, $relationshipItem, [ - 'action' => $this->routeProvider->buildLinkFormSaveRoute($customItem->getId(), $entityType, $entityId), + 'action' => $customItemRouteProvider->buildLinkFormSaveRoute($customItem->getId(), $entityType, $entityId), 'objectId' => $relationshipObject->getId(), 'contactId' => $entityId, ] ); - $form->handleRequest($this->request); + $form->handleRequest($request); if ($form->isValid()) { $callback = $relationshipItem->getId() ? null : 'customItemLinkFormPostSubmit'; - $relationshipItem = $this->customItemModel->save($relationshipItem); + $relationshipItem = $customItemModel->save($relationshipItem); $responseData = [ 'closeModal' => true, 'callback' => $callback, - 'flashes' => $this->renderView('MauticCoreBundle:Notification:flash_messages.html.php'), + 'flashes' => $this->renderView('@MauticCore/Notification/flash_messages.html.twig'), ]; return new JsonResponse($responseData); } } catch (ForbiddenException|NoRelationshipException|NotFoundException $e) { - $this->flashBag->add($e->getMessage(), [], FlashBag::LEVEL_ERROR); + $flashBag->add($e->getMessage(), [], FlashBag::LEVEL_ERROR); } return $this->delegateView( [ - 'returnUrl' => $this->routeProvider->buildContactViewRoute($entityId), + 'returnUrl' => $customItemRouteProvider->buildContactViewRoute($entityId), 'viewParameters' => [ 'entity' => $relationshipItem, 'customObject' => $relationshipObject, 'form' => $form->createView(), - 'tmpl' => $this->request->isXmlHttpRequest() ? $this->request->get('tmpl', 'index') : 'index', + 'tmpl' => $request->isXmlHttpRequest() ? $request->get('tmpl', 'index') : 'index', ], - 'contentTemplate' => 'CustomObjectsBundle:CustomItem:form.html.php', + 'contentTemplate' => '@CustomObjects/CustomItem/form.html.twig', 'passthroughVars' => [ 'closeModal' => false, 'callback' => 'customItemLinkFormLoad', 'mauticContent' => 'customItem', - 'route' => $this->routeProvider->buildLinkFormRoute($itemId, $entityType, $entityId), + 'route' => $customItemRouteProvider->buildLinkFormRoute($itemId, $entityType, $entityId), ], ] ); } - protected function getRelationshipItem(CustomObject $relationshipObject, CustomItem $customItem, string $entityType, int $entityId): CustomItem - { + protected function getRelationshipItem( + CustomItemModel $customItemModel, + CustomObject $relationshipObject, + CustomItem $customItem, + string $entityType, + int $entityId + ): CustomItem { /** @var CustomItemXrefCustomItem|null $relationshipItemXref */ $relationshipItemXref = $customItem->getCustomItemLowerReferences() - ->filter(function (CustomItemXrefCustomItem $item) use ($entityType, $entityId) { + ->filter(function (CustomItemXrefCustomItem $item) use ($entityType, $entityId): bool { $higher = $item->getCustomItemHigher(); return $higher->getRelationsByType($entityType) - ->filter(function ($relation) use ($entityId) { + ->filter(function ($relation) use ($entityId): bool { return (int) $relation->getLinkedEntity()->getId() === (int) $entityId; })->count() > 0; })->first(); - return $this->customItemModel->populateCustomFields( + return $customItemModel->populateCustomFields( $relationshipItemXref ? $relationshipItemXref->getCustomItemHigher() : new CustomItem($relationshipObject) ); } diff --git a/Controller/CustomItem/ListController.php b/Controller/CustomItem/ListController.php index 3dfed2e3e..381081f40 100644 --- a/Controller/CustomItem/ListController.php +++ b/Controller/CustomItem/ListController.php @@ -15,73 +15,34 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; use MauticPlugin\CustomObjectsBundle\Provider\SessionProviderFactory; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; class ListController extends CommonController { - /** - * @var RequestStack - */ - private $requestStack; - - /** - * @var SessionProviderFactory - */ - private $sessionProviderFactory; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomItemRouteProvider - */ - private $routeProvider; - - public function __construct( - RequestStack $requestStack, + public function listAction( SessionProviderFactory $sessionProviderFactory, CustomItemModel $customItemModel, CustomObjectModel $customObjectModel, CustomItemPermissionProvider $permissionProvider, - CustomItemRouteProvider $routeProvider - ) { - $this->requestStack = $requestStack; - $this->sessionProviderFactory = $sessionProviderFactory; - $this->customItemModel = $customItemModel; - $this->customObjectModel = $customObjectModel; - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - } + CustomItemRouteProvider $routeProvider, + int $objectId, + int $page = 1 + ): Response { + $request = $this->getCurrentRequest(); - public function listAction(int $objectId, int $page = 1): Response - { try { - $this->permissionProvider->canViewAtAll($objectId); - $customObject = $this->customObjectModel->fetchEntity($objectId); + $permissionProvider->canViewAtAll($objectId); + $customObject = $customObjectModel->fetchEntity($objectId); } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } - $request = $this->requestStack->getCurrentRequest(); $filterEntityId = (int) $request->get('filterEntityId'); $filterEntityType = InputHelper::clean($request->get('filterEntityType')); $lookup = (bool) $request->get('lookup'); - $sessionProvider = $this->sessionProviderFactory->createItemProvider($objectId, $filterEntityType, $filterEntityId, $lookup); + $sessionProvider = $sessionProviderFactory->createItemProvider($objectId, $filterEntityType, $filterEntityId, $lookup); $search = InputHelper::clean($request->get('search', $sessionProvider->getFilter())); $limit = (int) $request->get('limit', $sessionProvider->getPageLimit()); $orderBy = $sessionProvider->getOrderBy(CustomItem::TABLE_ALIAS.'.id'); @@ -105,8 +66,8 @@ public function listAction(int $objectId, int $page = 1): Response $sessionProvider->setPageLimit($limit); $sessionProvider->setFilter($search); - $route = $this->routeProvider->buildListRoute($objectId, $page, $filterEntityType ?: null, $filterEntityId ?: null, ['lookup' => $lookup ?: null]); - $items = $this->customItemModel->getTableData($tableConfig); + $route = $routeProvider->buildListRoute($objectId, $page, $filterEntityType ?: null, $filterEntityId ?: null, ['lookup' => $lookup ?: null]); + $items = $customItemModel->getTableData($tableConfig); $namespace = $sessionProvider->getNamespace(); $response = [ 'viewParameters' => [ @@ -116,7 +77,7 @@ public function listAction(int $objectId, int $page = 1): Response 'filterEntityType' => $filterEntityType, 'lookup' => $lookup, 'items' => $items, - 'itemCount' => $this->customItemModel->getCountForTable($tableConfig), + 'itemCount' => $customItemModel->getCountForTable($tableConfig), 'page' => $page, 'limit' => $limit, 'tmpl' => $request->isXmlHttpRequest() ? $request->get('tmpl', 'index') : 'index', @@ -124,7 +85,7 @@ public function listAction(int $objectId, int $page = 1): Response 'sessionVar' => $namespace, 'namespace' => $namespace, ], - 'contentTemplate' => 'CustomObjectsBundle:CustomItem:list.html.php', + 'contentTemplate' => '@CustomObjects/CustomItem/list.html.twig', 'passthroughVars' => [ 'mauticContent' => 'customItem', 'route' => $filterEntityType ? null : $route, @@ -132,7 +93,7 @@ public function listAction(int $objectId, int $page = 1): Response ]; if ($filterEntityId) { - $response['viewParameters']['fieldData'] = $this->customItemModel->getFieldListData($customObject, $items, $filterEntityType); + $response['viewParameters']['fieldData'] = $customItemModel->getFieldListData($customObject, $items, $filterEntityType); } if (!$request->isXmlHttpRequest()) { diff --git a/Controller/CustomItem/LookupController.php b/Controller/CustomItem/LookupController.php index 29d1255f8..38c4c813b 100644 --- a/Controller/CustomItem/LookupController.php +++ b/Controller/CustomItem/LookupController.php @@ -13,53 +13,25 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Request; class LookupController extends JsonController { - /** - * @var RequestStack - */ - private $requestStack; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var FlashBag - */ - private $flashBag; - - public function __construct( - RequestStack $requestStack, + public function listAction( + Request $request, CustomItemModel $customItemModel, CustomItemPermissionProvider $permissionProvider, - FlashBag $flashBag - ) { - $this->requestStack = $requestStack; - $this->customItemModel = $customItemModel; - $this->permissionProvider = $permissionProvider; - $this->flashBag = $flashBag; - } - - public function listAction(int $objectId): JsonResponse - { + FlashBag $flashBag, + int $objectId + ): JsonResponse { try { - $this->permissionProvider->canViewAtAll($objectId); + $permissionProvider->canViewAtAll($objectId); } catch (ForbiddenException $e) { - $this->flashBag->add($e->getMessage(), [], FlashBag::LEVEL_ERROR); + $flashBag->add($e->getMessage(), [], FlashBag::LEVEL_ERROR); return $this->renderJson(); } - $request = $this->requestStack->getCurrentRequest(); $search = InputHelper::clean($request->get('filter')); $filterEntityId = (int) $request->get('filterEntityId'); $filterEntityType = InputHelper::clean($request->get('filterEntityType')); @@ -69,6 +41,6 @@ public function listAction(int $objectId): JsonResponse $tableConfig->addParameter('filterEntityType', $filterEntityType); $tableConfig->addParameter('filterEntityId', $filterEntityId); - return $this->renderJson(['items' => $this->customItemModel->getLookupData($tableConfig)]); + return $this->renderJson(['items' => $customItemModel->getLookupData($tableConfig)]); } } diff --git a/Controller/CustomItem/SaveController.php b/Controller/CustomItem/SaveController.php index eea863601..0350b4800 100644 --- a/Controller/CustomItem/SaveController.php +++ b/Controller/CustomItem/SaveController.php @@ -17,93 +17,42 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; class SaveController extends AbstractFormController { - /** - * @var RequestStack - */ - private $requestStack; - - /** - * @var FormFactoryInterface - */ - private $formFactory; - - /** - * @var FlashBag - */ - private $flashBag; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomItemRouteProvider - */ - private $routeProvider; - - /** - * @var LockFlashMessageHelper - */ - private $lockFlashMessageHelper; - - public function __construct( - RequestStack $requestStack, + public function saveAction( FormFactoryInterface $formFactory, FlashBag $flashBag, CustomItemModel $customItemModel, CustomObjectModel $customObjectModel, CustomItemPermissionProvider $permissionProvider, CustomItemRouteProvider $routeProvider, - LockFlashMessageHelper $lockFlashMessageHelper - ) { - $this->requestStack = $requestStack; - $this->formFactory = $formFactory; - $this->flashBag = $flashBag; - $this->customItemModel = $customItemModel; - $this->customObjectModel = $customObjectModel; - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - $this->lockFlashMessageHelper = $lockFlashMessageHelper; - } + LockFlashMessageHelper $lockFlashMessageHelper, + int $objectId, + ?int $itemId = null + ): Response { + $request = $this->getCurrentRequest(); - public function saveAction(int $objectId, ?int $itemId = null): Response - { - $request = $this->requestStack->getCurrentRequest(); $customItemData = $request->request->get('custom_item'); $contactId = intval($customItemData['contact_id'] ?? 0); try { if ($itemId) { $message = 'mautic.core.notice.updated'; - $customItem = $this->customItemModel->fetchEntity($itemId); + $customItem = $customItemModel->fetchEntity($itemId); $route = 0 < $contactId - ? $this->routeProvider->buildEditRouteWithRedirectToContact($objectId, $itemId, $contactId) - : $this->routeProvider->buildEditRoute($objectId, $itemId); - $this->permissionProvider->canEdit($customItem); + ? $routeProvider->buildEditRouteWithRedirectToContact($objectId, $itemId, $contactId) + : $routeProvider->buildEditRoute($objectId, $itemId); + $permissionProvider->canEdit($customItem); } else { - $this->permissionProvider->canCreate($objectId); + $permissionProvider->canCreate($objectId); $message = 'mautic.core.notice.created'; - $customObject = $this->customObjectModel->fetchEntity($objectId); - $customItem = $this->customItemModel->populateCustomFields(new CustomItem($customObject)); + $customObject = $customObjectModel->fetchEntity($objectId); + $customItem = $customItemModel->populateCustomFields(new CustomItem($customObject)); $route = 0 < $contactId - ? $this->routeProvider->buildNewRouteWithRedirectToContact($objectId, $contactId) - : $this->routeProvider->buildNewRoute($objectId); + ? $routeProvider->buildNewRouteWithRedirectToContact($objectId, $contactId) + : $routeProvider->buildNewRoute($objectId); } } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); @@ -111,53 +60,53 @@ public function saveAction(int $objectId, ?int $itemId = null): Response return $this->accessDenied(false, $e->getMessage()); } - if ($this->customItemModel->isLocked($customItem)) { - $this->lockFlashMessageHelper->addFlash( + if ($customItemModel->isLocked($customItem)) { + $lockFlashMessageHelper->addFlash( $customItem, - $this->routeProvider->buildEditRoute($objectId, $itemId), + $routeProvider->buildEditRoute($objectId, $itemId), $this->canEdit($customItem), 'custom.item' ); - return $this->redirect($this->routeProvider->buildViewRoute($objectId, $itemId)); + return $this->redirect($routeProvider->buildViewRoute($objectId, $itemId)); } - $action = $this->routeProvider->buildSaveRoute($objectId, $itemId); + $action = $routeProvider->buildSaveRoute($objectId, $itemId); if (!$customItem->getId() && $customItem->getCustomObject()->getRelationshipObject() && $contactId) { $customItem->setChildCustomItem( - $this->customItemModel->populateCustomFields( + $customItemModel->populateCustomFields( new CustomItem($customItem->getCustomObject()->getRelationshipObject()) ) ); } - $form = $this->formFactory->create(CustomItemType::class, $customItem, ['action' => $action, 'objectId' => $objectId]); + $form = $formFactory->create(CustomItemType::class, $customItem, ['action' => $action, 'objectId' => $objectId]); $form->handleRequest($request); if ($form->isValid()) { - $customItem = $this->customItemModel->save($customItem); + $customItem = $customItemModel->save($customItem); if ($customItem->getChildCustomItem()) { $customItem->getChildCustomItem()->generateNameForChildObject('contact', $contactId, $customItem); - $customItem = $this->customItemModel->save($customItem->getChildCustomItem()); + $customItem = $customItemModel->save($customItem->getChildCustomItem()); } - if($customItem->hasBeenUpdated()){ + if ($customItem->hasBeenUpdated()) { $message = 'custom.item.notice.merged'; } - $this->flashBag->add( + $flashBag->add( $message, [ '%name%' => $customItem->getName(), - '%url%' => $this->routeProvider->buildEditRoute($objectId, $customItem->getId()), + '%url%' => $routeProvider->buildEditRoute($objectId, $customItem->getId()), ] ); $saveClicked = $form->get('buttons')->get('save')->isClicked(); - $detailView = 'CustomObjectsBundle:CustomItem\View:view'; - $formView = 'CustomObjectsBundle:CustomItem\Form:edit'; + $detailView = 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ViewController:viewAction'; + $formView = 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\FormController:editAction'; $pathParameters = [ 'objectId' => $objectId, @@ -167,25 +116,25 @@ public function saveAction(int $objectId, ?int $itemId = null): Response if (0 < $contactId) { // For parent-child items we want to link both items together and the child item with the contact. if ($customItem->getChildCustomItem()) { - $this->customItemModel->linkEntity($customItem->getChildCustomItem(), 'contact', $contactId); - $this->customItemModel->linkEntity($customItem->getChildCustomItem(), 'customItem', $customItem->getId()); + $customItemModel->linkEntity($customItem->getChildCustomItem(), 'contact', $contactId); + $customItemModel->linkEntity($customItem->getChildCustomItem(), 'customItem', $customItem->getId()); } // For parent items we want to connect the parent item directly to the contact. - $this->customItemModel->linkEntity($customItem, 'contact', $contactId); + $customItemModel->linkEntity($customItem, 'contact', $contactId); if ($saveClicked) { return $this->redirectToRoute('mautic_contact_action', ['objectAction' => 'view', 'objectId' => $contactId]); } - $formView = 'CustomObjectsBundle:CustomItem\Form:editWithRedirectToContact'; + $formView = 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\FormController:editWithRedirectToContactAction'; $pathParameters['contactId'] = $contactId; } $request->setMethod(Request::METHOD_GET); if ($saveClicked) { - $this->customItemModel->unlockEntity($customItem); + $customItemModel->unlockEntity($customItem); } return $this->forward( @@ -203,7 +152,7 @@ public function saveAction(int $objectId, ?int $itemId = null): Response 'form' => $form->createView(), 'tmpl' => $request->isXmlHttpRequest() ? $request->get('tmpl', 'index') : 'index', ], - 'contentTemplate' => 'CustomObjectsBundle:CustomItem:form.html.php', + 'contentTemplate' => '@CustomObjects/CustomItem/form.html.twig', 'passthroughVars' => [ 'mauticContent' => 'customItem', 'route' => $route, diff --git a/Controller/CustomItem/UnlinkController.php b/Controller/CustomItem/UnlinkController.php index 9e1a68698..fd0a724d5 100644 --- a/Controller/CustomItem/UnlinkController.php +++ b/Controller/CustomItem/UnlinkController.php @@ -11,61 +11,41 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use Symfony\Component\HttpFoundation\JsonResponse; -use UnexpectedValueException; class UnlinkController extends JsonController { - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var FlashBag - */ - private $flashBag; - - public function __construct( + public function saveAction( CustomItemModel $customItemModel, CustomItemPermissionProvider $permissionProvider, - FlashBag $flashBag - ) { - $this->customItemModel = $customItemModel; - $this->permissionProvider = $permissionProvider; - $this->flashBag = $flashBag; - } - - public function saveAction(int $itemId, string $entityType, int $entityId): JsonResponse - { + FlashBag $flashBag, + int $itemId, + string $entityType, + int $entityId + ): JsonResponse { try { - $customItem = $this->customItemModel->fetchEntity($itemId); + $customItem = $customItemModel->fetchEntity($itemId); - $this->permissionProvider->canEdit($customItem); + $permissionProvider->canEdit($customItem); if ($customItem->getCustomObject()->getRelationshipObject()) { try { $childCustomItem = $customItem->findChildCustomItem(); - } catch (NotFoundException $e) { + } catch (NotFoundException) { } if (isset($childCustomItem)) { - $this->customItemModel->delete($childCustomItem); + $customItemModel->delete($childCustomItem); } } - $this->customItemModel->unlinkEntity($customItem, $entityType, $entityId); + $customItemModel->unlinkEntity($customItem, $entityType, $entityId); - $this->flashBag->add( + $flashBag->add( 'custom.item.unlinked', ['%itemId%' => $customItem->getId(), '%itemName%' => $customItem->getName(), '%entityType%' => $entityType, '%entityId%' => $entityId] ); - } catch (ForbiddenException|NotFoundException|UnexpectedValueException $e) { - $this->flashBag->add($e->getMessage(), [], FlashBag::LEVEL_ERROR); + } catch (ForbiddenException|NotFoundException|\UnexpectedValueException $e) { + $flashBag->add($e->getMessage(), [], FlashBag::LEVEL_ERROR); } return $this->renderJson(); diff --git a/Controller/CustomItem/ViewController.php b/Controller/CustomItem/ViewController.php index c29166ba9..62885f8cd 100644 --- a/Controller/CustomItem/ViewController.php +++ b/Controller/CustomItem/ViewController.php @@ -14,88 +14,44 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; class ViewController extends CommonController { - /** - * @var RequestStack - */ - private $requestStack; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var CustomItemXrefContactModel - */ - private $customItemXrefContactModel; - - /** - * @var AuditLogModel - */ - private $auditLogModel; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomItemRouteProvider - */ - private $routeProvider; - - /** - * @var FormFactoryInterface - */ - private $formFactory; - - public function __construct( - RequestStack $requestStack, + public function viewAction( FormFactoryInterface $formFactory, CustomItemModel $customItemModel, CustomItemXrefContactModel $customItemXrefContactModel, AuditLogModel $auditLogModel, CustomItemPermissionProvider $permissionProvider, - CustomItemRouteProvider $routeProvider - ) { - $this->requestStack = $requestStack; - $this->formFactory = $formFactory; - $this->customItemModel = $customItemModel; - $this->customItemXrefContactModel = $customItemXrefContactModel; - $this->auditLogModel = $auditLogModel; - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - } + CustomItemRouteProvider $routeProvider, + int $objectId, + int $itemId + ): Response { + $request = $this->getCurrentRequest(); - public function viewAction(int $objectId, int $itemId): Response - { try { - $customItem = $this->customItemModel->fetchEntity($itemId); - $this->permissionProvider->canView($customItem); + $customItem = $customItemModel->fetchEntity($itemId); + $permissionProvider->canView($customItem); } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } - $route = $this->routeProvider->buildViewRoute($objectId, $itemId); - $dateRangeForm = $this->formFactory->create( + $route = $routeProvider->buildViewRoute($objectId, $itemId); + $dateRangeForm = $formFactory->create( DateRangeType::class, - $this->requestStack->getCurrentRequest()->get('daterange', []), + $request->get('daterange', []), ['action' => $route] ); - $stats = $this->customItemXrefContactModel->getLinksLineChartData( + $stats = $customItemXrefContactModel->getLinksLineChartData( new \DateTime($dateRangeForm->get('date_from')->getData()), new \DateTime($dateRangeForm->get('date_to')->getData()), $customItem ); - $auditLogs = $this->auditLogModel->getLogForObject('customItem', $itemId, $customItem->getDateAdded(), 10, 'customObjects'); + $auditLogs = $auditLogModel->getLogForObject('customItem', $itemId, $customItem->getDateAdded(), 10, 'customObjects'); return $this->delegateView( [ @@ -106,7 +62,7 @@ public function viewAction(int $objectId, int $itemId): Response 'stats' => $stats, 'logs' => $auditLogs, 'contacts' => $this->forward( - 'CustomObjectsBundle:CustomItem\ContactList:list', + 'MauticPlugin\CustomObjectsBundle\Controller\CustomItem\ContactListController::listAction', [ 'objectId' => $itemId, 'page' => 1, @@ -114,7 +70,7 @@ public function viewAction(int $objectId, int $itemId): Response ] )->getContent(), ], - 'contentTemplate' => 'CustomObjectsBundle:CustomItem:detail.html.php', + 'contentTemplate' => '@CustomObjects/CustomItem/detail.html.twig', 'passthroughVars' => [ 'mauticContent' => 'customItem', 'activeLink' => "#mautic_custom_object_{$objectId}", diff --git a/Controller/CustomObject/CancelController.php b/Controller/CustomObject/CancelController.php index d0c0ec82f..97798ef5d 100644 --- a/Controller/CustomObject/CancelController.php +++ b/Controller/CustomObject/CancelController.php @@ -12,45 +12,24 @@ class CancelController extends CommonController { - /** - * @var SessionProviderFactory - */ - private $sessionProviderFactory; - - /** - * @var CustomObjectRouteProvider - */ - private $routeProvider; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - public function __construct( + public function cancelAction( SessionProviderFactory $sessionProviderFactory, CustomObjectRouteProvider $routeProvider, - CustomObjectModel $customObjectModel - ) { - $this->sessionProviderFactory = $sessionProviderFactory; - $this->routeProvider = $routeProvider; - $this->customObjectModel = $customObjectModel; - } - - public function cancelAction(?int $objectId): Response - { - $page = $this->sessionProviderFactory->createObjectProvider()->getPage(); + CustomObjectModel $customObjectModel, + ?int $objectId + ): Response { + $page = $sessionProviderFactory->createObjectProvider()->getPage(); if ($objectId) { - $customObject = $this->customObjectModel->fetchEntity($objectId); - $this->customObjectModel->unlockEntity($customObject); + $customObject = $customObjectModel->fetchEntity($objectId); + $customObjectModel->unlockEntity($customObject); } return $this->postActionRedirect( [ - 'returnUrl' => $this->routeProvider->buildListRoute($page), + 'returnUrl' => $routeProvider->buildListRoute($page), 'viewParameters' => ['page' => $page], - 'contentTemplate' => 'CustomObjectsBundle:CustomObject\List:list', + 'contentTemplate' => 'MauticPlugin\CustomObjectsBundle\Controller\CustomObject\ListController:listAction', 'passthroughVars' => [ 'mauticContent' => 'customObject', ], diff --git a/Controller/CustomObject/DeleteController.php b/Controller/CustomObject/DeleteController.php index 3bd6e6b95..4eb96c95a 100644 --- a/Controller/CustomObject/DeleteController.php +++ b/Controller/CustomObject/DeleteController.php @@ -19,61 +19,28 @@ class DeleteController extends CommonController { - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var SessionProviderFactory - */ - private $sessionProviderFactory; - - /** - * @var FlashBag - */ - private $flashBag; - - /** - * @var CustomObjectPermissionProvider - */ - private $permissionProvider; - - /** - * @var EventDispatcherInterface - */ - private $eventDispatcher; - - public function __construct( - CustomObjectModel $customObjectModel, + public function deleteAction( SessionProviderFactory $sessionProviderFactory, + CustomObjectModel $customObjectModel, FlashBag $flashBag, CustomObjectPermissionProvider $permissionProvider, - EventDispatcherInterface $eventDispatcher - ) { - $this->customObjectModel = $customObjectModel; - $this->sessionProviderFactory = $sessionProviderFactory; - $this->flashBag = $flashBag; - $this->permissionProvider = $permissionProvider; - $this->eventDispatcher = $eventDispatcher; - } - - public function deleteAction(int $objectId): Response - { - $controller = 'CustomObjectsBundle:CustomObject\List:list'; + EventDispatcherInterface $eventDispatcher, + int $objectId + ): Response { + $controller = 'MauticPlugin\CustomObjectsBundle\Controller\CustomObject\ListController:listAction'; $page = [ - 'page' => $this->sessionProviderFactory->createObjectProvider()->getPage(), + 'page' => $sessionProviderFactory->createObjectProvider()->getPage(), ]; try { - $customObject = $this->customObjectModel->fetchEntity($objectId); + $customObject = $customObjectModel->fetchEntity($objectId); $translationParameters = [ '%name%' => $customObject->getName(), '%id%' => $customObject->getId(), ]; - $this->permissionProvider->canDelete($customObject); - $this->customObjectModel->checkIfTheCustomObjectIsUsedInSegmentFilters($customObject); + $permissionProvider->canDelete($customObject); + $customObjectModel->checkIfTheCustomObjectIsUsedInSegmentFilters($customObject); } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); } catch (ForbiddenException $e) { @@ -85,7 +52,7 @@ public function deleteAction(int $objectId): Response } $translationParameters['%segments%'] = implode(', ', $segments); - $this->flashBag->add('custom.object.error.used.in.segments', $translationParameters, FlashBag::LEVEL_ERROR); + $flashBag->add('custom.object.error.used.in.segments', $translationParameters, FlashBag::LEVEL_ERROR); return $this->forward( $controller, @@ -94,8 +61,8 @@ public function deleteAction(int $objectId): Response } $customObjectEvent = new CustomObjectEvent($customObject); - $customObjectEvent->setFlashBag($this->flashBag); - $this->eventDispatcher->dispatch(CustomObjectEvents::ON_CUSTOM_OBJECT_USER_PRE_DELETE, $customObjectEvent); + $customObjectEvent->setFlashBag($flashBag); + $eventDispatcher->dispatch($customObjectEvent, CustomObjectEvents::ON_CUSTOM_OBJECT_USER_PRE_DELETE); return $this->forward( $controller, diff --git a/Controller/CustomObject/FormController.php b/Controller/CustomObject/FormController.php index 5d3284d6e..581b00c1f 100644 --- a/Controller/CustomObject/FormController.php +++ b/Controller/CustomObject/FormController.php @@ -15,136 +15,130 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectRouteProvider; -use Symfony\Component\Form\FormFactory; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\Response; class FormController extends AbstractFormController { - /** - * @var FormFactory - */ - private $formFactory; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomFieldModel - */ - private $customFieldModel; - - /** - * @var CustomObjectPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomObjectRouteProvider - */ - private $routeProvider; - - /** - * @var CustomFieldTypeProvider - */ - private $customFieldTypeProvider; - - /** - * @var LockFlashMessageHelper - */ - private $lockFlashMessageHelper; - - public function __construct( - FormFactory $formFactory, - CustomObjectModel $customObjectModel, - CustomFieldModel $customFieldModel, + public function newAction( CustomObjectPermissionProvider $permissionProvider, + FormFactoryInterface $formFactory, CustomObjectRouteProvider $routeProvider, CustomFieldTypeProvider $customFieldTypeProvider, - LockFlashMessageHelper $lockFlashMessageHelper - ) { - $this->formFactory = $formFactory; - $this->customObjectModel = $customObjectModel; - $this->customFieldModel = $customFieldModel; - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - $this->customFieldTypeProvider = $customFieldTypeProvider; - $this->lockFlashMessageHelper = $lockFlashMessageHelper; - } - - public function newAction(): Response - { + CustomFieldModel $customFieldModel + ): Response { try { - $this->permissionProvider->canCreate(); + $permissionProvider->canCreate(); $customObject = new CustomObject(); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } - return $this->renderForm($customObject, $this->routeProvider->buildNewRoute()); + return $this->renderFormForObject( + $formFactory, + $routeProvider, + $customFieldTypeProvider, + $customFieldModel, + $customObject, + $routeProvider->buildNewRoute() + ); } - public function editAction(int $objectId): Response - { + public function editAction( + CustomObjectModel $customObjectModel, + CustomObjectPermissionProvider $permissionProvider, + LockFlashMessageHelper $lockFlashMessageHelper, + FormFactoryInterface $formFactory, + CustomObjectRouteProvider $routeProvider, + CustomFieldTypeProvider $customFieldTypeProvider, + CustomFieldModel $customFieldModel, + int $objectId + ): Response { try { - $customObject = $this->customObjectModel->fetchEntity($objectId); - $this->permissionProvider->canEdit($customObject); + $customObject = $customObjectModel->fetchEntity($objectId); + $permissionProvider->canEdit($customObject); } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } - if ($this->customObjectModel->isLocked($customObject)) { - $this->lockFlashMessageHelper->addFlash( + if ($customObjectModel->isLocked($customObject)) { + $lockFlashMessageHelper->addFlash( $customObject, - $this->routeProvider->buildEditRoute($objectId), + $routeProvider->buildEditRoute($objectId), $this->canEdit($customObject), 'custom.object' ); - return $this->redirect($this->routeProvider->buildViewRoute($objectId)); + return $this->redirect($routeProvider->buildViewRoute($objectId)); } - $this->customObjectModel->lockEntity($customObject); + $customObjectModel->lockEntity($customObject); - return $this->renderForm($customObject, $this->routeProvider->buildEditRoute($objectId)); + return $this->renderFormForObject( + $formFactory, + $routeProvider, + $customFieldTypeProvider, + $customFieldModel, + $customObject, + $routeProvider->buildEditRoute($objectId) + ); } - public function cloneAction(int $objectId): Response - { + public function cloneAction( + CustomObjectModel $customObjectModel, + CustomObjectPermissionProvider $permissionProvider, + FormFactoryInterface $formFactory, + CustomObjectRouteProvider $routeProvider, + CustomFieldTypeProvider $customFieldTypeProvider, + CustomFieldModel $customFieldModel, + int $objectId + ): Response { try { - $customObject = clone $this->customObjectModel->fetchEntity($objectId); - $this->permissionProvider->canClone($customObject); + $customObject = clone $customObjectModel->fetchEntity($objectId); + $permissionProvider->canClone($customObject); } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } - return $this->renderForm($customObject, $this->routeProvider->buildCloneRoute($objectId)); + return $this->renderFormForObject( + $formFactory, + $routeProvider, + $customFieldTypeProvider, + $customFieldModel, + $customObject, + $routeProvider->buildCloneRoute($objectId) + ); } - private function renderForm(CustomObject $customObject, string $route): Response - { - $form = $this->formFactory->create( + private function renderFormForObject( + FormFactoryInterface $formFactory, + CustomObjectRouteProvider $routeProvider, + CustomFieldTypeProvider $customFieldTypeProvider, + CustomFieldModel $customFieldModel, + CustomObject $customObject, + string $route + ): Response { + $form = $formFactory->create( CustomObjectType::class, $customObject, - ['action' => $this->routeProvider->buildSaveRoute($customObject->getId())] + ['action' => $routeProvider->buildSaveRoute($customObject->getId())] ); return $this->delegateView( [ - 'returnUrl' => $this->routeProvider->buildListRoute(), + 'returnUrl' => $routeProvider->buildListRoute(), 'viewParameters' => [ 'customObject' => $customObject, - 'availableFieldTypes' => $this->customFieldTypeProvider->getTypes(), - 'customFields' => $this->customFieldModel->fetchCustomFieldsForObject($customObject), + 'availableFieldTypes' => $customFieldTypeProvider->getTypes(), + 'customFields' => $customFieldModel->fetchCustomFieldsForObject($customObject), 'deletedFields' => [], 'form' => $form->createView(), ], - 'contentTemplate' => 'CustomObjectsBundle:CustomObject:form.html.php', + 'contentTemplate' => '@CustomObjects/CustomObject/form.html.twig', 'passthroughVars' => [ 'mauticContent' => 'customObject', 'route' => $route, diff --git a/Controller/CustomObject/ListController.php b/Controller/CustomObject/ListController.php index ab8af89b5..130186518 100644 --- a/Controller/CustomObject/ListController.php +++ b/Controller/CustomObject/ListController.php @@ -13,65 +13,31 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectRouteProvider; use MauticPlugin\CustomObjectsBundle\Provider\SessionProviderFactory; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; class ListController extends CommonController { - /** - * @var RequestStack - */ - private $requestStack; - - /** - * @var SessionProviderFactory - */ - private $sessionProviderFactory; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomObjectPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomObjectRouteProvider - */ - private $routeProvider; - - public function __construct( - RequestStack $requestStack, + public function listAction( SessionProviderFactory $sessionProviderFactory, CustomObjectModel $customObjectModel, CustomObjectPermissionProvider $permissionProvider, - CustomObjectRouteProvider $routeProvider - ) { - $this->requestStack = $requestStack; - $this->sessionProviderFactory = $sessionProviderFactory; - $this->customObjectModel = $customObjectModel; - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - } + CustomObjectRouteProvider $routeProvider, + int $page = 1 + ): Response { + $request = $this->getCurrentRequest(); - public function listAction(int $page = 1): Response - { try { - $this->permissionProvider->canViewAtAll(); + $permissionProvider->canViewAtAll(); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } - $request = $this->requestStack->getCurrentRequest(); - $sessionProvider = $this->sessionProviderFactory->createObjectProvider(); + $sessionProvider = $sessionProviderFactory->createObjectProvider(); $search = InputHelper::clean($request->get('search', $sessionProvider->getFilter())); $limit = (int) $request->get('limit', $sessionProvider->getPageLimit()); $orderBy = $sessionProvider->getOrderBy(CustomObject::TABLE_ALIAS.'.id'); $orderByDir = $sessionProvider->getOrderByDir('ASC'); - $route = $this->routeProvider->buildListRoute($page); + $route = $routeProvider->buildListRoute($page); if ($request->query->has('orderby')) { $orderBy = InputHelper::clean($request->query->get('orderby'), true); @@ -91,14 +57,14 @@ public function listAction(int $page = 1): Response 'returnUrl' => $route, 'viewParameters' => [ 'searchValue' => $search, - 'items' => $this->customObjectModel->getTableData($tableConfig), - 'count' => $this->customObjectModel->getCountForTable($tableConfig), + 'items' => $customObjectModel->getTableData($tableConfig), + 'count' => $customObjectModel->getCountForTable($tableConfig), 'page' => $page, 'limit' => $limit, 'tmpl' => $request->isXmlHttpRequest() ? $request->get('tmpl', 'index') : 'index', 'sessionVar' => $sessionProvider->getNamespace(), ], - 'contentTemplate' => 'CustomObjectsBundle:CustomObject:list.html.php', + 'contentTemplate' => '@CustomObjects/CustomObject/list.html.twig', 'passthroughVars' => [ 'mauticContent' => 'customObject', 'route' => $route, diff --git a/Controller/CustomObject/SaveController.php b/Controller/CustomObject/SaveController.php index c77f2dd52..603a569c7 100644 --- a/Controller/CustomObject/SaveController.php +++ b/Controller/CustomObject/SaveController.php @@ -22,68 +22,11 @@ use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; class SaveController extends AbstractFormController { - /** - * @var RequestStack - */ - private $requestStack; - - /** - * @var FlashBag - */ - private $flashBag; - - /** - * @var FormFactoryInterface - */ - private $formFactory; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomFieldModel - */ - private $customFieldModel; - - /** - * @var CustomObjectPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomObjectRouteProvider - */ - private $routeProvider; - - /** - * @var CustomFieldTypeProvider - */ - private $customFieldTypeProvider; - - /** - * @var ParamsToStringTransformer - */ - private $paramsToStringTransformer; - - /** - * @var OptionsToStringTransformer - */ - private $optionsToStringTransformer; - - /** - * @var LockFlashMessageHelper - */ - private $lockFlashMessageHelper; - - public function __construct( - RequestStack $requestStack, + public function saveAction( FlashBag $flashBag, FormFactoryInterface $formFactory, CustomObjectModel $customObjectModel, @@ -93,29 +36,17 @@ public function __construct( CustomFieldTypeProvider $customFieldTypeProvider, ParamsToStringTransformer $paramsToStringTransformer, OptionsToStringTransformer $optionsToStringTransformer, - LockFlashMessageHelper $lockFlashMessageHelper - ) { - $this->requestStack = $requestStack; - $this->flashBag = $flashBag; - $this->formFactory = $formFactory; - $this->customObjectModel = $customObjectModel; - $this->customFieldModel = $customFieldModel; - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - $this->customFieldTypeProvider = $customFieldTypeProvider; - $this->paramsToStringTransformer = $paramsToStringTransformer; - $this->optionsToStringTransformer = $optionsToStringTransformer; - $this->lockFlashMessageHelper = $lockFlashMessageHelper; - } + LockFlashMessageHelper $lockFlashMessageHelper, + ?int $objectId = null + ): Response { + $request = $this->getCurrentRequest(); - public function saveAction(?int $objectId = null): Response - { try { - $customObject = $objectId ? $this->customObjectModel->fetchEntity($objectId) : new CustomObject(); + $customObject = $objectId ? $customObjectModel->fetchEntity($objectId) : new CustomObject(); if ($customObject->isNew()) { - $this->permissionProvider->canCreate(); + $permissionProvider->canCreate(); } else { - $this->permissionProvider->canEdit($customObject); + $permissionProvider->canEdit($customObject); } } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); @@ -123,20 +54,19 @@ public function saveAction(?int $objectId = null): Response return $this->accessDenied(false, $e->getMessage()); } - if ($this->customObjectModel->isLocked($customObject)) { - $this->lockFlashMessageHelper->addFlash( + if ($customObjectModel->isLocked($customObject)) { + $lockFlashMessageHelper->addFlash( $customObject, - $this->routeProvider->buildEditRoute($objectId), + $routeProvider->buildEditRoute($objectId), $this->canEdit($customObject), 'custom.object' ); - return $this->redirect($this->routeProvider->buildViewRoute($objectId)); + return $this->redirect($routeProvider->buildViewRoute($objectId)); } - $request = $this->requestStack->getCurrentRequest(); - $action = $this->routeProvider->buildSaveRoute($objectId); - $form = $this->formFactory->create( + $action = $routeProvider->buildSaveRoute($objectId); + $form = $formFactory->create( CustomObjectType::class, $customObject, ['action' => $action] @@ -148,23 +78,29 @@ public function saveAction(?int $objectId = null): Response $form->submit($postData, false); if ($form->isValid()) { - $this->handleRawPost($customObject, $postData); + $this->handleRawPost( + $customObjectModel, + $paramsToStringTransformer, + $optionsToStringTransformer, + $customObject, + $postData + ); - $this->customObjectModel->save($customObject); + $customObjectModel->save($customObject); - $this->flashBag->add( + $flashBag->add( $objectId ? 'mautic.core.notice.updated' : 'mautic.core.notice.created', [ '%name%' => $customObject->getName(), - '%url%' => $this->routeProvider->buildEditRoute($objectId), + '%url%' => $routeProvider->buildEditRoute($objectId), ] ); if ($form->get('buttons')->get('save')->isClicked()) { - $this->customObjectModel->unlockEntity($customObject); - $route = $this->routeProvider->buildViewRoute($customObject->getId()); + $customObjectModel->unlockEntity($customObject); + $route = $routeProvider->buildViewRoute($customObject->getId()); } else { - $route = $this->routeProvider->buildEditRoute($customObject->getId()); + $route = $routeProvider->buildEditRoute($customObject->getId()); } return $this->redirectWithCompletePageRefresh($request, $route); @@ -172,18 +108,18 @@ public function saveAction(?int $objectId = null): Response return $this->delegateView( [ - 'returnUrl' => $this->routeProvider->buildListRoute(), + 'returnUrl' => $routeProvider->buildListRoute(), 'viewParameters' => [ 'customObject' => $customObject, - 'availableFieldTypes' => $this->customFieldTypeProvider->getTypes(), - 'customFields' => $this->customFieldModel->fetchCustomFieldsForObject($customObject), + 'availableFieldTypes' => $customFieldTypeProvider->getTypes(), + 'customFields' => $customFieldModel->fetchCustomFieldsForObject($customObject), 'deletedFields' => [], 'form' => $form->createView(), ], - 'contentTemplate' => 'CustomObjectsBundle:CustomObject:form.html.php', + 'contentTemplate' => '@CustomObjects/CustomObject/form.html.twig', 'passthroughVars' => [ 'mauticContent' => 'customObject', - 'route' => $objectId ? $this->routeProvider->buildEditRoute($customObject->getId()) : $this->routeProvider->buildNewRoute(), + 'route' => $objectId ? $routeProvider->buildEditRoute($customObject->getId()) : $routeProvider->buildNewRoute(), ], ] ); @@ -192,18 +128,23 @@ public function saveAction(?int $objectId = null): Response /** * @param string[] $rawCustomObject */ - private function handleRawPost(CustomObject $customObject, array $rawCustomObject): void - { + private function handleRawPost( + CustomObjectModel $customObjectModel, + ParamsToStringTransformer $paramsToStringTransformer, + OptionsToStringTransformer $optionsToStringTransformer, + CustomObject $customObject, + array $rawCustomObject + ): void { if (empty($rawCustomObject['customFields'])) { return; } - // Let's order received $_POST data and apply delete for existing CFs + // Let's order received $_POST data and apply to delete for existing CFs $customFields = []; foreach ($rawCustomObject['customFields'] as $customField) { if ($customField['deleted'] && $customField['id']) { // Remove deleted custom fields - $this->customObjectModel->removeCustomFieldById($customObject, (int) $customField['id']); + $customObjectModel->removeCustomFieldById($customObject, (int) $customField['id']); } else { // We are using order key as key to access collection of CustomFields below $customFields[(int) $customField['order']] = $customField; @@ -213,10 +154,10 @@ private function handleRawPost(CustomObject $customObject, array $rawCustomObjec foreach ($customFields as $order => $rawCustomField) { // Should be resolved better in form/transformer, but here it is more clear $params = $rawCustomField['params']; - $params = $this->paramsToStringTransformer->reverseTransform($params); + $params = $paramsToStringTransformer->reverseTransform($params); $options = $rawCustomField['options']; - $options = $this->optionsToStringTransformer->reverseTransform($options); + $options = $optionsToStringTransformer->reverseTransform($options); /** @var CustomField $customField */ $customField = $customObject->getCustomFieldByOrder((int) $order); diff --git a/Controller/CustomObject/ViewController.php b/Controller/CustomObject/ViewController.php index 222e5ee66..d8dd3e449 100644 --- a/Controller/CustomObject/ViewController.php +++ b/Controller/CustomObject/ViewController.php @@ -13,81 +13,42 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectRouteProvider; use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; class ViewController extends CommonController { - /** - * @var RequestStack - */ - private $requestStack; - - /** - * @var FormFactoryInterface - */ - private $formFactory; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var AuditLogModel - */ - private $auditLogModel; - - /** - * @var CustomObjectPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomObjectRouteProvider - */ - private $routeProvider; - - public function __construct( - RequestStack $requestStack, + public function viewAction( FormFactoryInterface $formFactory, CustomObjectModel $customObjectModel, AuditLogModel $auditLogModel, CustomObjectPermissionProvider $permissionProvider, - CustomObjectRouteProvider $routeProvider - ) { - $this->requestStack = $requestStack; - $this->formFactory = $formFactory; - $this->customObjectModel = $customObjectModel; - $this->auditLogModel = $auditLogModel; - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - } + CustomObjectRouteProvider $routeProvider, + int $objectId + ): Response { + $request = $this->getCurrentRequest(); - public function viewAction(int $objectId): Response - { try { - $customObject = $this->customObjectModel->fetchEntity($objectId); - $this->permissionProvider->canView($customObject); + $customObject = $customObjectModel->fetchEntity($objectId); + $permissionProvider->canView($customObject); } catch (NotFoundException $e) { return $this->notFound($e->getMessage()); } catch (ForbiddenException $e) { return $this->accessDenied(false, $e->getMessage()); } - $route = $this->routeProvider->buildViewRoute($objectId); - $dateRangeForm = $this->formFactory->create( + $route = $routeProvider->buildViewRoute($objectId); + $dateRangeForm = $formFactory->create( DateRangeType::class, - $this->requestStack->getCurrentRequest()->get('daterange', []), + $request->get('daterange', []), ['action' => $route] ); - $stats = $this->customObjectModel->getItemsLineChartData( + $stats = $customObjectModel->getItemsLineChartData( new \DateTime($dateRangeForm->get('date_from')->getData()), new \DateTime($dateRangeForm->get('date_to')->getData()), $customObject ); - $auditLogs = $this->auditLogModel->getLogForObject( + $auditLogs = $auditLogModel->getLogForObject( 'customObject', $objectId, $customObject->getDateAdded(), @@ -104,7 +65,7 @@ public function viewAction(int $objectId): Response 'stats' => $stats, 'logs' => $auditLogs, ], - 'contentTemplate' => 'CustomObjectsBundle:CustomObject:detail.html.php', + 'contentTemplate' => '@CustomObjects/CustomObject/detail.html.twig', 'passthroughVars' => [ 'mauticContent' => 'customObject', 'activeLink' => "#mautic_custom_object_{$objectId}", diff --git a/Controller/JsonController.php b/Controller/JsonController.php index 77a86d128..331f27363 100644 --- a/Controller/JsonController.php +++ b/Controller/JsonController.php @@ -4,10 +4,10 @@ namespace MauticPlugin\CustomObjectsBundle\Controller; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; -class JsonController extends Controller +class JsonController extends AbstractController { /** * Adds flashes stored in session (by addFlash() method) to the JsonResponse. @@ -16,7 +16,7 @@ class JsonController extends Controller */ protected function renderJson(array $responseData = []): JsonResponse { - $responseData['flashes'] = $this->renderView('MauticCoreBundle:Notification:flash_messages.html.php'); + $responseData['flashes'] = $this->renderView('@MauticCore/Notification/flash_messages.html.twig'); return new JsonResponse($responseData); } diff --git a/CustomFieldType/AbstractCustomFieldType.php b/CustomFieldType/AbstractCustomFieldType.php index ff96d4563..5a8b3199e 100644 --- a/CustomFieldType/AbstractCustomFieldType.php +++ b/CustomFieldType/AbstractCustomFieldType.php @@ -10,9 +10,9 @@ use MauticPlugin\CustomObjectsBundle\Exception\UndefinedTransformerException; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; -abstract class AbstractCustomFieldType implements CustomFieldTypeInterface +abstract class AbstractCustomFieldType implements CustomFieldTypeInterface, \Stringable { /** * @var string @@ -24,22 +24,10 @@ abstract class AbstractCustomFieldType implements CustomFieldTypeInterface */ protected $formTypeOptions = []; - /** - * @var TranslatorInterface - */ - protected $translator; - - /** - * @var FilterOperatorProviderInterface - */ - protected $filterOperatorProvider; - public function __construct( - TranslatorInterface $translator, - FilterOperatorProviderInterface $filterOperatorProvider + protected TranslatorInterface $translator, + protected FilterOperatorProviderInterface $filterOperatorProvider ) { - $this->translator = $translator; - $this->filterOperatorProvider = $filterOperatorProvider; } public function __toString(): string @@ -110,8 +98,8 @@ public function hasChoices(): bool { $type = $this->getSymfonyFormFieldType(); - return ChoiceType::class === $type || - is_subclass_of($this->getSymfonyFormFieldType(), ChoiceType::class); + return ChoiceType::class === $type + || is_subclass_of($this->getSymfonyFormFieldType(), ChoiceType::class); } /** diff --git a/CustomFieldType/AbstractMultivalueType.php b/CustomFieldType/AbstractMultivalueType.php index 9d85c71ab..e46757d22 100644 --- a/CustomFieldType/AbstractMultivalueType.php +++ b/CustomFieldType/AbstractMultivalueType.php @@ -16,25 +16,18 @@ use MauticPlugin\CustomObjectsBundle\Helper\CsvHelper; use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; abstract class AbstractMultivalueType extends AbstractCustomFieldType { public const TABLE_NAME = 'custom_field_value_option'; - /** - * @var CsvHelper - */ - private $csvHelper; - public function __construct( TranslatorInterface $translator, FilterOperatorProviderInterface $filterOperatorProvider, - CsvHelper $csvHelper + private CsvHelper $csvHelper ) { parent::__construct($translator, $filterOperatorProvider); - - $this->csvHelper = $csvHelper; } /** @@ -94,7 +87,7 @@ public function validateValue(CustomField $customField, $value): void } $options = $customField->getOptions(); - $possibleValues = $options->map(function (CustomFieldOption $option) { + $possibleValues = $options->map(function (CustomFieldOption $option): string { return $option->getValue(); })->getValues(); @@ -129,7 +122,7 @@ public function valueToString(CustomFieldValueInterface $fieldValue): string foreach ($values as $value) { try { $labels[] = $fieldValue->getCustomField()->valueToLabel((string) $value); - } catch (NotFoundException $e) { + } catch (NotFoundException) { // When the value does not exist anymore, use the value instead. $labels[] = $value; } diff --git a/CustomFieldType/CountryType.php b/CustomFieldType/CountryType.php index a6dfa364c..71969db5a 100644 --- a/CustomFieldType/CountryType.php +++ b/CustomFieldType/CountryType.php @@ -23,7 +23,7 @@ class CountryType extends SelectType implements StaticChoiceTypeInterface /** * @var string[] */ - private $countryList; + private ?array $countryList = null; /** * {@inheritdoc} diff --git a/CustomFieldType/DataTransformer/CsvTransformer.php b/CustomFieldType/DataTransformer/CsvTransformer.php index e0f756f00..6173f0c7d 100644 --- a/CustomFieldType/DataTransformer/CsvTransformer.php +++ b/CustomFieldType/DataTransformer/CsvTransformer.php @@ -9,10 +9,7 @@ class CsvTransformer implements DataTransformerInterface { - /** - * @var CsvHelper - */ - private $csvHelper; + private CsvHelper $csvHelper; public function __construct() { diff --git a/CustomFieldType/DataTransformer/DateTimeAtomTransformer.php b/CustomFieldType/DataTransformer/DateTimeAtomTransformer.php index 46028ef57..96317e535 100644 --- a/CustomFieldType/DataTransformer/DateTimeAtomTransformer.php +++ b/CustomFieldType/DataTransformer/DateTimeAtomTransformer.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\CustomFieldType\DataTransformer; -use DateTimeImmutable; use Symfony\Component\Form\DataTransformerInterface; class DateTimeAtomTransformer implements DataTransformerInterface @@ -15,7 +14,7 @@ class DateTimeAtomTransformer implements DataTransformerInterface public function transform($value) { if ($value) { - return new DateTimeImmutable($value); + return new \DateTimeImmutable($value); } return null; diff --git a/CustomFieldType/DataTransformer/DateTimeTransformer.php b/CustomFieldType/DataTransformer/DateTimeTransformer.php index 9bf96fb7c..77bb081cd 100644 --- a/CustomFieldType/DataTransformer/DateTimeTransformer.php +++ b/CustomFieldType/DataTransformer/DateTimeTransformer.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\CustomFieldType\DataTransformer; -use DateTime; use Symfony\Component\Form\DataTransformerInterface; class DateTimeTransformer implements DataTransformerInterface @@ -15,7 +14,7 @@ class DateTimeTransformer implements DataTransformerInterface public function transform($value) { if ($value) { - return new DateTime($value); + return new \DateTime($value); } return null; diff --git a/CustomFieldType/DataTransformer/DateTransformer.php b/CustomFieldType/DataTransformer/DateTransformer.php index 19c439503..9855405ee 100644 --- a/CustomFieldType/DataTransformer/DateTransformer.php +++ b/CustomFieldType/DataTransformer/DateTransformer.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\CustomFieldType\DataTransformer; -use DateTime; use Symfony\Component\Form\DataTransformerInterface; class DateTransformer implements DataTransformerInterface @@ -15,7 +14,7 @@ class DateTransformer implements DataTransformerInterface public function transform($value) { if ($value) { - return new DateTime($value); + return new \DateTime($value); } return null; @@ -31,7 +30,7 @@ public function reverseTransform($value) } if (is_string($value)) { - $value = new DateTime($value); + $value = new \DateTime($value); } return $value->format('Y-m-d'); diff --git a/CustomFieldType/DateOperatorTrait.php b/CustomFieldType/DateOperatorTrait.php new file mode 100644 index 000000000..c81d9f73c --- /dev/null +++ b/CustomFieldType/DateOperatorTrait.php @@ -0,0 +1,38 @@ +getValue(); - if ($value instanceof DateTimeInterface) { + if ($value instanceof \DateTimeInterface) { return $value->format('Y-m-d H:i:s'); } diff --git a/CustomFieldType/DateType.php b/CustomFieldType/DateType.php index 9d7b81626..d2fcd09b7 100644 --- a/CustomFieldType/DateType.php +++ b/CustomFieldType/DateType.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\CustomFieldType; -use DateTimeInterface; use MauticPlugin\CustomObjectsBundle\CustomFieldType\DataTransformer\DateTransformer; use MauticPlugin\CustomObjectsBundle\CustomFieldType\DataTransformer\ViewDateTransformer; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; @@ -16,6 +15,8 @@ class DateType extends AbstractCustomFieldType { + use DateOperatorTrait; + /** * @var string */ @@ -70,17 +71,6 @@ public function getEntityClass(): string return CustomFieldValueDate::class; } - /** - * @return mixed[] - */ - public function getOperators(): array - { - $allOperators = parent::getOperators(); - $allowedOperators = array_flip(['=', '!=', 'gt', 'gte', 'lt', 'lte', 'empty', '!empty']); - - return array_intersect_key($allOperators, $allowedOperators); - } - /** * {@inheritdoc} */ @@ -112,7 +102,7 @@ public function valueToString(CustomFieldValueInterface $fieldValue): string { $value = $fieldValue->getValue(); - if ($value instanceof DateTimeInterface) { + if ($value instanceof \DateTimeInterface) { return $value->format('Y-m-d'); } diff --git a/CustomFieldType/IntType.php b/CustomFieldType/IntType.php index dc20ba308..d4e1c95c1 100644 --- a/CustomFieldType/IntType.php +++ b/CustomFieldType/IntType.php @@ -41,13 +41,27 @@ public function createValueEntity(CustomField $customField, CustomItem $customIt return new CustomFieldValueInt($customField, $customItem, (int) $value); } + /** + * Remove operators that are supported only by segment filters. + * + * @return string[] + */ + public function getOperatorOptions(): array + { + $options = parent::getOperatorOptions(); + + unset($options['between'], $options['!between']); + + return $options; + } + /** * @return mixed[] */ public function getOperators(): array { $allOperators = parent::getOperators(); - $allowedOperators = array_flip(['=', '!=', 'gt', 'gte', 'lt', 'lte', 'empty', '!empty']); + $allowedOperators = array_flip(['=', '!=', 'gt', 'gte', 'lt', 'lte', 'empty', '!empty', 'between', '!between']); return array_intersect_key($allOperators, $allowedOperators); } diff --git a/CustomFieldType/PhoneType.php b/CustomFieldType/PhoneType.php index 5efab7d9a..a7790dcd2 100644 --- a/CustomFieldType/PhoneType.php +++ b/CustomFieldType/PhoneType.php @@ -36,10 +36,8 @@ public function validateValue(CustomField $customField, $value): void try { $phoneNumber = $phoneUtil->parse($value, PhoneNumberUtil::UNKNOWN_REGION); - } catch (NumberParseException $e) { + } catch (NumberParseException) { throw new \UnexpectedValueException($message); - - return; } if (false === $phoneUtil->isValidNumber($phoneNumber)) { diff --git a/CustomFieldType/SelectType.php b/CustomFieldType/SelectType.php index d9d3a0950..3ff8b5a8e 100644 --- a/CustomFieldType/SelectType.php +++ b/CustomFieldType/SelectType.php @@ -53,7 +53,7 @@ public function valueToString(CustomFieldValueInterface $fieldValue): string try { return $fieldValue->getCustomField()->valueToLabel((string) $value); - } catch (NotFoundException $e) { + } catch (NotFoundException) { // When the value does not exist anymore, use the value instead. return $value; } diff --git a/CustomItemEvents.php b/CustomItemEvents.php index 6ee649120..e040afdf5 100644 --- a/CustomItemEvents.php +++ b/CustomItemEvents.php @@ -14,7 +14,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomItemEvent + * @see Event\CustomItemEvent * * @var string */ @@ -25,7 +25,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomItemEvent + * @see Event\CustomItemEvent * * @var string */ @@ -36,7 +36,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomItemEvent + * @see Event\CustomItemEvent * * @var string */ @@ -47,7 +47,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomItemEvent + * @see Event\CustomItemEvent * * @var string */ @@ -58,7 +58,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomItemListQueryEvent + * @see Event\CustomItemListQueryEvent * * @var string */ @@ -69,7 +69,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomItemListQueryEvent + * @see Event\CustomItemListQueryEvent * * @var string */ @@ -80,7 +80,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomItemListQueryEvent + * @see Event\CustomItemListQueryEvent * * @var string */ @@ -91,7 +91,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomItemXrefEntityDiscoveryEvent + * @see Event\CustomItemXrefEntityDiscoveryEvent * * @var string */ @@ -102,7 +102,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomItemXrefEntityEvent + * @see Event\CustomItemXrefEntityEvent * * @var string */ @@ -113,7 +113,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomItemXrefEntityEvent + * @see Event\CustomItemXrefEntityEvent * * @var string */ @@ -124,7 +124,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \Mautic\CampaignBundle\Event\CampaignExecutionEvent + * @see Event\CampaignExecutionEvent * * @var string */ @@ -135,7 +135,7 @@ final class CustomItemEvents * * The event listener receives a * - * @see \Mautic\CampaignBundle\Event\CampaignExecutionEvent + * @see Event\CampaignExecutionEvent * * @var string */ @@ -144,7 +144,7 @@ final class CustomItemEvents /** * The custom.item.on_custom_item_export event is fired when the custom item is being exported. * - * @see MauticPlugin\CustomObjectsBundle\Event\CustomItemExportSchedulerEvent + * @see Event\CustomItemExportSchedulerEvent * * @var string */ @@ -153,7 +153,7 @@ final class CustomItemEvents /** * The custom.item.custom_item_prepare_export_file event is fired when the custom item data is being prepared to be exported. * - * @see MauticPlugin\CustomObjectsBundle\Event\CustomItemExportSchedulerEvent + * @see Event\CustomItemExportSchedulerEvent * * @var string */ diff --git a/CustomObjectEvents.php b/CustomObjectEvents.php index 6116107ac..2ef16f1c4 100644 --- a/CustomObjectEvents.php +++ b/CustomObjectEvents.php @@ -14,7 +14,7 @@ final class CustomObjectEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomObjectEvent + * @see Event\CustomObjectEvent * * @var string */ @@ -25,7 +25,7 @@ final class CustomObjectEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomObjectEvent + * @see Event\CustomObjectEvent * * @var string */ @@ -36,7 +36,7 @@ final class CustomObjectEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomObjectEvent + * @see Event\CustomObjectEvent * * @var string */ @@ -47,7 +47,7 @@ final class CustomObjectEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomObjectEvent + * @see Event\CustomObjectEvent * * @var string */ @@ -58,7 +58,7 @@ final class CustomObjectEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomObjectEvent + * @see Event\CustomObjectEvent * * @var string */ @@ -69,7 +69,7 @@ final class CustomObjectEvents * * The event listener receives a * - * @see \MauticPlugin\CustomObjectsBundle\Event\CustomObjectListFormatEvent + * @see Event\CustomObjectListFormatEvent * * @var string */ diff --git a/DTO/CustomItemFieldListData.php b/DTO/CustomItemFieldListData.php index fb7e1f823..aa440bc3c 100644 --- a/DTO/CustomItemFieldListData.php +++ b/DTO/CustomItemFieldListData.php @@ -8,20 +8,8 @@ class CustomItemFieldListData { - /** - * @var array - */ - private $columns; - - /** - * @var array - */ - private $data; - - public function __construct(array $columns, array $data) + public function __construct(private array $columns, private array $data) { - $this->columns = $columns; - $this->data = $data; } public function getColumnLabels(): array diff --git a/DTO/ImportLogDTO.php b/DTO/ImportLogDTO.php new file mode 100644 index 000000000..14b4338dc --- /dev/null +++ b/DTO/ImportLogDTO.php @@ -0,0 +1,28 @@ + + */ + private array $warnings = []; + + public function hasWarning(): bool + { + return !empty($this->warnings); + } + + public function addWarning(string $warning): void + { + $this->warnings[] = $warning; + } + + public function getWarningsAsString(): string + { + return implode('\n', $this->warnings); + } +} diff --git a/DTO/TableConfig.php b/DTO/TableConfig.php index 3d37011f4..70132dd11 100644 --- a/DTO/TableConfig.php +++ b/DTO/TableConfig.php @@ -10,37 +10,17 @@ class TableConfig { - /** - * @var int - */ - private $limit; - - /** - * @var int - */ - private $page; - - /** - * @var string - */ - private $orderBy; - - /** - * @var string - */ - private $orderDirection; - /** * @var mixed[] */ - private $parameters = []; - - public function __construct(int $limit, int $page, string $orderBy, string $orderDirection = 'ASC') - { - $this->limit = $limit; - $this->page = $page; - $this->orderBy = $orderBy; - $this->orderDirection = $orderDirection; + private array $parameters = []; + + public function __construct( + private int $limit, + private int $page, + private string $orderBy, + private string $orderDirection = 'ASC' + ) { } public function getOrderBy(): string diff --git a/DTO/Token.php b/DTO/Token.php index 7deea6f7c..cfa38fa2d 100644 --- a/DTO/Token.php +++ b/DTO/Token.php @@ -11,49 +11,22 @@ */ class Token { - /** - * @var string - */ - private $token; - - /** - * @var int - */ - private $limit = 1; - - /** - * @var string - */ - private $where = ''; - - /** - * @var string - */ - private $order = 'latest'; - - /** - * @var string - */ - private $defaultValue = ''; - - /** - * @var string - */ - private $format = ''; - - /** - * @var string - */ - private $customFieldAlias = ''; - - /** - * @var string - */ - private $customObjectAlias = ''; - - public function __construct(string $token) - { - $this->token = $token; + private int $limit = 1; + + private string $where = ''; + + private string $order = 'latest'; + + private string $defaultValue = ''; + + private string $format = ''; + + private string $customFieldAlias = ''; + + private string $customObjectAlias = ''; + + public function __construct(private string $token) + { } public function setDefaultValue(string $defaultValue): void diff --git a/DataPersister/CustomItemDataPersister.php b/DataPersister/CustomItemDataPersister.php new file mode 100644 index 000000000..e35043b55 --- /dev/null +++ b/DataPersister/CustomItemDataPersister.php @@ -0,0 +1,46 @@ +customItemModel->save($data); + + return $data; + } + + /** + * @param mixed $data + */ + public function remove($data): void + { + \assert($data instanceof CustomItem); + + $this->customItemModel->delete($data); + } +} diff --git a/DependencyInjection/CustomObjectsExtension.php b/DependencyInjection/CustomObjectsExtension.php new file mode 100644 index 000000000..f54828d57 --- /dev/null +++ b/DependencyInjection/CustomObjectsExtension.php @@ -0,0 +1,22 @@ +load('services.php'); + } +} diff --git a/Entity/AbstractCustomFieldValue.php b/Entity/AbstractCustomFieldValue.php index abb4907f8..a4cdacbba 100644 --- a/Entity/AbstractCustomFieldValue.php +++ b/Entity/AbstractCustomFieldValue.php @@ -12,16 +12,6 @@ abstract class AbstractCustomFieldValue implements CustomFieldValueInterface { - /** - * @var CustomField - */ - protected $customField; - - /** - * @var CustomItem - */ - protected $customItem; - public static function loadMetadata(ORM\ClassMetadata $metadata): void { $builder = new ClassMetadataBuilder($metadata); @@ -29,10 +19,8 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void $builder->setMappedSuperClass(); } - public function __construct(CustomField $customField, CustomItem $customItem) + public function __construct(protected CustomField $customField, protected CustomItem $customItem) { - $this->customField = $customField; - $this->customItem = $customItem; } public static function loadValidatorMetadata(ClassMetadata $metadata): void @@ -81,7 +69,7 @@ public function getCustomItem(): CustomItem /** * @param mixed $value */ - public function addValue($value = null) + public function addValue($value = null): void { throw new \Exception('addValue is not implemented for '.self::class); } diff --git a/Entity/CustomField.php b/Entity/CustomField.php index 198494cc1..1c77ade48 100644 --- a/Entity/CustomField.php +++ b/Entity/CustomField.php @@ -11,7 +11,6 @@ use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; -use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping\JoinColumn; @@ -51,6 +50,7 @@ * normalizationContext={"groups"={"custom_field:read"}, "swagger_definition_name"="Read"}, * denormalizationContext={"groups"={"custom_field:write"}, "swagger_definition_name"="Write"} * ) + * * @ApiFilter(SearchFilter::class, properties={"alias": "partial"}) */ class CustomField extends FormEntity implements UniqueEntityInterface, UuidInterface @@ -62,7 +62,9 @@ class CustomField extends FormEntity implements UniqueEntityInterface, UuidInter /** * @var int|null + * * @Groups({"custom_field:read", "custom_object:read"}) + * * @ApiProperty( * attributes={ * "openapi_context"={ @@ -77,7 +79,9 @@ class CustomField extends FormEntity implements UniqueEntityInterface, UuidInter /** * @var string|null + * * @Groups({"custom_field:read", "custom_field:write", "custom_object:read", "custom_object:write"}) + * * @ApiProperty( * attributes={ * "openapi_context"={ @@ -93,7 +97,9 @@ class CustomField extends FormEntity implements UniqueEntityInterface, UuidInter /** * @var string|null + * * @Groups({"custom_field:read", "custom_field:write", "custom_object:read", "custom_object:write"}) + * * @ApiProperty( * attributes={ * "openapi_context"={ @@ -109,7 +115,9 @@ class CustomField extends FormEntity implements UniqueEntityInterface, UuidInter /** * @var string|null + * * @Groups({"custom_field:read", "custom_field:write", "custom_object:read", "custom_object:write"}) + * * @ApiProperty( * attributes={ * "openapi_context"={ @@ -143,7 +151,9 @@ class CustomField extends FormEntity implements UniqueEntityInterface, UuidInter /** * @ManyToOne(targetEntity="CustomObject", inversedBy="customFields") + * * @JoinColumn(name="custom_object_id", referencedColumnName="id") + * * @Groups({"custom_field:read", "custom_field:write", "custom_object:read", "custom_object:write"}) * * @var CustomObject|null @@ -152,6 +162,7 @@ class CustomField extends FormEntity implements UniqueEntityInterface, UuidInter /** * @Groups({"custom_field:read", "custom_field:write", "custom_object:read", "custom_object:write"}) + * * @ApiProperty( * attributes={ * "openapi_context"={ @@ -168,26 +179,32 @@ class CustomField extends FormEntity implements UniqueEntityInterface, UuidInter /** * @var bool + * * @Groups({"custom_field:read", "custom_field:write", "custom_object:read", "custom_object:write"}) */ private $required = false; /** * @var mixed + * * @Groups({"custom_field:read", "custom_field:write", "custom_object:read", "custom_object:write"}) */ private $defaultValue; /** * @var Collection|CustomFieldOption[] + * * @OneToMany(targetEntity="CustomFieldOption", mappedBy="customField") + * * @Groups({"custom_field:read", "custom_field:write", "custom_object:read", "custom_object:write"}) + * * @ApiSubresource() */ private $options; /** * @var Params|string[] + * * @Groups({"custom_field:read", "custom_field:write", "custom_object:read", "custom_object:write"}) */ private $params; @@ -203,11 +220,10 @@ class CustomField extends FormEntity implements UniqueEntityInterface, UuidInter private $showInContactDetailList = true; /** - * @var bool * @Groups({"custom_field:read", "custom_field:write", "custom_object:read", "custom_object:write"}) */ private bool $isUniqueIdentifier = false; - + private bool $wasChangeIsUniqueIdentifier = false; public function __construct() @@ -221,9 +237,9 @@ public function __clone() $this->alias = null; } - public function __toString() + public function __toString(): string { - return $this->getLabel(); + return (string) $this->getLabel(); } /** @@ -256,20 +272,20 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void ->build(); $builder->addId(); - $builder->addField('label', Type::STRING); - $builder->addField('alias', Type::STRING); - $builder->addField('type', Type::STRING); + $builder->addField('label', Types::STRING); + $builder->addField('alias', Types::STRING); + $builder->addField('type', Types::STRING); $builder->createField('order', 'integer') ->columnName('field_order') ->nullable() ->build(); - $builder->createField('required', Type::BOOLEAN) + $builder->createField('required', Types::BOOLEAN) ->columnName('required') ->option('default', false) ->build(); - $builder->createField('defaultValue', Type::STRING) + $builder->createField('defaultValue', Types::STRING) ->columnName('default_value') ->nullable() ->build(); @@ -281,17 +297,17 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void ->fetchExtraLazy() ->build(); - $builder->createField('params', Type::JSON_ARRAY) + $builder->createField('params', Types::JSON) ->columnName('params') ->nullable() ->build(); - $builder->createField('showInCustomObjectDetailList', Type::BOOLEAN) + $builder->createField('showInCustomObjectDetailList', Types::BOOLEAN) ->columnName('show_in_custom_object_detail_list') ->option('default', true) ->build(); - $builder->createField('showInContactDetailList', Type::BOOLEAN) + $builder->createField('showInContactDetailList', Types::BOOLEAN) ->columnName('show_in_contact_detail_list') ->option('default', true) ->build(); @@ -366,7 +382,7 @@ public function getName(): ?string /** * @param string|null $alias */ - public function setAlias($alias) + public function setAlias($alias): void { $this->isChanged('alias', $alias); $this->alias = $alias; @@ -418,6 +434,15 @@ public function getFormFieldOptions(array $customOptions = []): array 'attr' => ['class' => 'form-control'], ]; + if ('datetime' === $this->getType()) { + $fieldOptions = array_merge( + $fieldOptions, + [ + 'html5' => false, + ] + ); + } + if ($placeholder) { $fieldOptions['attr']['data-placeholder'] = $placeholder; } @@ -434,9 +459,6 @@ public function getCustomObject(): ?CustomObject return $this->customObject; } - /** - * @param CustomObject $customObject - */ public function setCustomObject(?CustomObject $customObject = null): void { $this->customObject = $customObject; @@ -460,9 +482,6 @@ public function isRequired(): bool return $this->required; } - /** - * @param bool $required - */ public function setRequired(?bool $required): void { $this->required = $this->isUniqueIdentifier ?: (bool) $required; @@ -475,7 +494,7 @@ public function getDefaultValue() { try { return $this->getTypeObject()->createDefaultValueTransformer()->transform($this->defaultValue); - } catch (UndefinedTransformerException $e) { + } catch (UndefinedTransformerException) { // Nothing to transform, return string below } @@ -491,7 +510,7 @@ public function setDefaultValue($defaultValue): void $this->defaultValue = $this->getTypeObject()->createDefaultValueTransformer()->reverseTransform($defaultValue); return; - } catch (UndefinedTransformerException $e) { + } catch (UndefinedTransformerException) { // Nothing to transform, use string below } @@ -579,7 +598,7 @@ public function valueToLabel(string $value): string throw new NotFoundException("Label was not found for value {$value}"); } - return $label; + return (string) $label; } /** @@ -629,8 +648,8 @@ public function setShowInContactDetailList(?bool $showInContactDetailList): void public function isChoiceType(): bool { - return ChoiceType::class === $this->getTypeObject()->getSymfonyFormFieldType() || - is_subclass_of($this->getTypeObject()->getSymfonyFormFieldType(), ChoiceType::class); + return ChoiceType::class === $this->getTypeObject()->getSymfonyFormFieldType() + || is_subclass_of($this->getTypeObject()->getSymfonyFormFieldType(), ChoiceType::class); } public function canHaveMultipleValues(): bool @@ -668,7 +687,7 @@ public function getIsPublished() /** * @Groups({"custom_field:read", "custom_object:read"}) * - * @return \DateTime + * @return \DateTimeInterface|null */ public function getDateAdded() { @@ -678,7 +697,7 @@ public function getDateAdded() /** * @Groups({"custom_field:read", "custom_object:read"}) * - * @return \DateTime + * @return \DateTimeInterface|null */ public function getDateModified() { diff --git a/Entity/CustomFieldFactory.php b/Entity/CustomFieldFactory.php index 7b14cd48e..abe900830 100644 --- a/Entity/CustomFieldFactory.php +++ b/Entity/CustomFieldFactory.php @@ -10,14 +10,8 @@ class CustomFieldFactory { - /** - * @var CustomFieldTypeProvider - */ - private $customFieldTypeProvider; - - public function __construct(CustomFieldTypeProvider $customFieldTypeProvider) + public function __construct(private CustomFieldTypeProvider $customFieldTypeProvider) { - $this->customFieldTypeProvider = $customFieldTypeProvider; } /** diff --git a/Entity/CustomFieldOption.php b/Entity/CustomFieldOption.php index 3843fd72a..f76e68eef 100644 --- a/Entity/CustomFieldOption.php +++ b/Entity/CustomFieldOption.php @@ -5,9 +5,8 @@ namespace MauticPlugin\CustomObjectsBundle\Entity; use ApiPlatform\Core\Annotation\ApiResource; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; -use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\JoinColumn; use Doctrine\ORM\Mapping\ManyToOne; @@ -35,27 +34,34 @@ class CustomFieldOption implements \ArrayAccess { /** * @var CustomField|null + * * @Id @Column(type="integer") + * * @ManyToOne(targetEntity="CustomField", inversedBy="options") + * * @JoinColumn("custom_field_id") */ private $customField; /** * @var string|null + * * @Groups({"custom_object:read", "custom_object:write", "custom_field:read", "custom_field:write"}) */ private $label; /** * @var string|null + * * @Id @Column(type="integer") + * * @Groups({"custom_object:read", "custom_object:write", "custom_field:read", "custom_field:write"}) */ private $value; /** * @var int|null + * * @Groups({"custom_object:read", "custom_field:read"}) */ private $order; @@ -99,11 +105,11 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void ->makePrimaryKey() ->build(); - $builder->createField('value', Type::STRING) + $builder->createField('value', Types::STRING) ->makePrimaryKey() ->build(); - $builder->addField('label', Type::STRING); + $builder->addField('label', Types::STRING); $builder->createField('order', 'integer') ->columnName('option_order') @@ -164,7 +170,7 @@ public function setOrder(?int $order): void /** * {@inheritdoc} */ - public function offsetExists($offset) + public function offsetExists(mixed $offset): bool { return isset($this->{$offset}); } @@ -172,7 +178,7 @@ public function offsetExists($offset) /** * {@inheritdoc} */ - public function offsetGet($offset) + public function offsetGet(mixed $offset): mixed { return $this->offsetExists($offset) ? $this->{$offset} : null; } @@ -180,7 +186,7 @@ public function offsetGet($offset) /** * {@inheritdoc} */ - public function offsetSet($offset, $value) + public function offsetSet(mixed $offset, mixed $value): void { $this->{$offset} = $value; } @@ -188,7 +194,7 @@ public function offsetSet($offset, $value) /** * {@inheritdoc} */ - public function offsetUnset($offset) + public function offsetUnset(mixed $offset): void { $this->{$offset} = null; } diff --git a/Entity/CustomFieldValueDate.php b/Entity/CustomFieldValueDate.php index 844d45074..d06c2b377 100644 --- a/Entity/CustomFieldValueDate.php +++ b/Entity/CustomFieldValueDate.php @@ -4,19 +4,18 @@ namespace MauticPlugin\CustomObjectsBundle\Entity; -use DateTimeInterface; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder; class CustomFieldValueDate extends AbstractCustomFieldValue { /** - * @var DateTimeInterface|null + * @var \DateTimeInterface|null */ private $value; - public function __construct(CustomField $customField, CustomItem $customItem, ?DateTimeInterface $value = null) + public function __construct(CustomField $customField, CustomItem $customItem, ?\DateTimeInterface $value = null) { parent::__construct($customField, $customItem); @@ -28,7 +27,7 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void $builder = new ClassMetadataBuilder($metadata); $builder->setTable('custom_field_value_date'); $builder->addIndex(['value'], 'value_index'); - $builder->addNullableField('value', Type::DATE); + $builder->addNullableField('value', Types::DATETIME_MUTABLE); parent::addReferenceColumns($builder); } @@ -44,7 +43,7 @@ public function setValue($value = null): void return; } - if (!$value instanceof DateTimeInterface) { + if (!$value instanceof \DateTimeInterface) { $value = new \DateTimeImmutable($value); } diff --git a/Entity/CustomFieldValueDateTime.php b/Entity/CustomFieldValueDateTime.php index f696ff2f5..891588c41 100644 --- a/Entity/CustomFieldValueDateTime.php +++ b/Entity/CustomFieldValueDateTime.php @@ -4,23 +4,15 @@ namespace MauticPlugin\CustomObjectsBundle\Entity; -use DateTimeInterface; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder; class CustomFieldValueDateTime extends AbstractCustomFieldValue { - /** - * @var DateTimeInterface|null - */ - private $value; - - public function __construct(CustomField $customField, CustomItem $customItem, ?DateTimeInterface $value = null) + public function __construct(CustomField $customField, CustomItem $customItem, private ?\DateTimeInterface $value = null) { parent::__construct($customField, $customItem); - - $this->value = $value; } public static function loadMetadata(ORM\ClassMetadata $metadata): void @@ -28,7 +20,7 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void $builder = new ClassMetadataBuilder($metadata); $builder->setTable('custom_field_value_datetime'); $builder->addIndex(['value'], 'value_index'); - $builder->addNullableField('value', Type::DATETIME); + $builder->addNullableField('value', Types::DATETIME_MUTABLE); parent::addReferenceColumns($builder); } @@ -44,7 +36,7 @@ public function setValue($value = null): void return; } - if (!$value instanceof DateTimeInterface) { + if (!$value instanceof \DateTimeInterface) { $value = new \DateTimeImmutable($value); } diff --git a/Entity/CustomFieldValueInt.php b/Entity/CustomFieldValueInt.php index d1378cf84..ac42f2341 100644 --- a/Entity/CustomFieldValueInt.php +++ b/Entity/CustomFieldValueInt.php @@ -4,22 +4,15 @@ namespace MauticPlugin\CustomObjectsBundle\Entity; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder; class CustomFieldValueInt extends AbstractCustomFieldValue { - /** - * @var int|null - */ - private $value; - - public function __construct(CustomField $customField, CustomItem $customItem, ?int $value = null) + public function __construct(CustomField $customField, CustomItem $customItem, private ?int $value = null) { parent::__construct($customField, $customItem); - - $this->value = $value; } public static function loadMetadata(ORM\ClassMetadata $metadata): void @@ -27,7 +20,7 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void $builder = new ClassMetadataBuilder($metadata); $builder->setTable('custom_field_value_int'); $builder->addIndex(['value'], 'value_index'); - $builder->addNullableField('value', Type::INTEGER); + $builder->addNullableField('value', Types::INTEGER); parent::addReferenceColumns($builder); } diff --git a/Entity/CustomFieldValueOption.php b/Entity/CustomFieldValueOption.php index 7ae077a9a..742dbcc2f 100644 --- a/Entity/CustomFieldValueOption.php +++ b/Entity/CustomFieldValueOption.php @@ -14,7 +14,15 @@ class CustomFieldValueOption extends AbstractCustomFieldValue { /** + * The identifier of the record, used by Doctrine ORM. + * * @var int|null + * + * @ORM\Id + * + * @ORM\Column(type="integer") + * + * @ORM\GeneratedValue */ private $id; @@ -59,7 +67,7 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void /** * @param mixed $value */ - public function addValue($value = null) + public function addValue($value = null): void { if (!$this->value) { $this->value = []; @@ -75,7 +83,7 @@ public function addValue($value = null) /** * @param mixed $value */ - public function setValue($value = null) + public function setValue($value = null): void { if (is_array($value)) { $value = array_unique($value); diff --git a/Entity/CustomFieldValueText.php b/Entity/CustomFieldValueText.php index 30082eab5..598af5f87 100644 --- a/Entity/CustomFieldValueText.php +++ b/Entity/CustomFieldValueText.php @@ -4,22 +4,15 @@ namespace MauticPlugin\CustomObjectsBundle\Entity; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder; class CustomFieldValueText extends AbstractCustomFieldValue { - /** - * @var string|null - */ - private $value; - - public function __construct(CustomField $customField, CustomItem $customItem, ?string $value = null) + public function __construct(CustomField $customField, CustomItem $customItem, private ?string $value = null) { parent::__construct($customField, $customItem); - - $this->value = $value; } /** @@ -30,7 +23,7 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void { $builder = new ClassMetadataBuilder($metadata); $builder->setTable('custom_field_value_text') - ->addNullableField('value', Type::TEXT) + ->addNullableField('value', Types::TEXT) ->addFulltextIndex(['value'], 'value_fulltext'); parent::addReferenceColumns($builder); diff --git a/Entity/CustomItem.php b/Entity/CustomItem.php index 2c5b4df8b..99a658f9a 100644 --- a/Entity/CustomItem.php +++ b/Entity/CustomItem.php @@ -8,7 +8,6 @@ use ApiPlatform\Core\Annotation\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; -use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping\JoinColumn; @@ -42,6 +41,7 @@ * denormalizationContext={"groups"={"custom_item:write"}, "swagger_definition_name"="Write"} * ) */ +#[\AllowDynamicProperties] class CustomItem extends FormEntity implements UniqueEntityInterface, UpsertInterface { use UpsertTrait; @@ -50,7 +50,9 @@ class CustomItem extends FormEntity implements UniqueEntityInterface, UpsertInte /** * @var int|null + * * @Groups({"custom_item:read"}) + * * @ApiProperty( * attributes={ * "openapi_context"={ @@ -65,7 +67,9 @@ class CustomItem extends FormEntity implements UniqueEntityInterface, UpsertInte /** * @var string|null + * * @Groups({"custom_item:read", "custom_item:write"}) + * * @ApiProperty( * attributes={ * "openapi_context"={ @@ -79,14 +83,6 @@ class CustomItem extends FormEntity implements UniqueEntityInterface, UpsertInte */ private $name; - /** - * @var CustomObject - * @ManyToOne(targetEntity="CustomObject") - * @JoinColumn(name="custom_object_id", referencedColumnName="id") - * @Groups({"custom_item:read", "custom_item:write"}) - */ - private $customObject; - /** * @var CustomItem|null */ @@ -94,7 +90,9 @@ class CustomItem extends FormEntity implements UniqueEntityInterface, UpsertInte /** * @var string|null + * * @Groups({"custom_item:read", "custom_item:write"}) + * * @ApiProperty( * attributes={ * "openapi_context"={ @@ -109,9 +107,13 @@ class CustomItem extends FormEntity implements UniqueEntityInterface, UpsertInte /** * @var Category|null + * * @ManyToOne(targetEntity="Category") + * * @JoinColumn(name="category_id", referencedColumnName="id") + * * @ApiProperty(readableLink=false, writableLink=false) + * * @Groups({"custom_item:read", "custom_item:write"}) **/ private $category; @@ -123,6 +125,7 @@ class CustomItem extends FormEntity implements UniqueEntityInterface, UpsertInte /** * @var array + * * @ApiProperty( * attributes={ * "openapi_context"={ @@ -149,6 +152,7 @@ class CustomItem extends FormEntity implements UniqueEntityInterface, UpsertInte * } * } * ) + * * @Groups({"custom_item:read", "custom_item:write"}) */ private $fieldValues; @@ -175,9 +179,17 @@ class CustomItem extends FormEntity implements UniqueEntityInterface, UpsertInte private ?string $uniqueHash = null; - public function __construct(CustomObject $customObject) - { - $this->customObject = $customObject; + public function __construct(/** + * @var CustomObject + * + * @ManyToOne(targetEntity="CustomObject") + * + * @JoinColumn(name="custom_object_id", referencedColumnName="id") + * + * @Groups({"custom_item:read", "custom_item:write"}) + */ + private CustomObject $customObject + ) { $this->customFieldValues = new ArrayCollection(); $this->contactReferences = new ArrayCollection(); $this->companyReferences = new ArrayCollection(); @@ -225,8 +237,8 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void $builder->addBigIntIdField(); $builder->addCategory(); - $builder->addField('name', Type::STRING); - $builder->addNullableField('language', Type::STRING, 'lang'); + $builder->addField('name', Types::STRING); + $builder->addNullableField('language', Types::STRING, 'lang'); } public static function loadValidatorMetadata(ClassMetadata $metadata): void @@ -242,14 +254,12 @@ public function populateFromArray(array $data): void { foreach ($data as $property => $value) { $camelCaseProperty = lcfirst(ucwords($property, '_')); + // $this->__set($camelCaseProperty, $value); $this->{$camelCaseProperty} = $value; } } - /** - * @return int|null - */ - public function getId() + public function getId(): int { return (int) $this->id; } @@ -257,7 +267,7 @@ public function getId() /** * @param string|null $name */ - public function setName($name) + public function setName($name): void { $this->isChanged('name', $name); $this->name = $name; @@ -295,7 +305,7 @@ public function getCategory() /** * @param Category|null $category */ - public function setCategory($category) + public function setCategory($category): void { $this->isChanged('category', $category ? $category : null); $this->category = $category; @@ -312,7 +322,7 @@ public function getLanguage() /** * @param string|null $language */ - public function setLanguage($language) + public function setLanguage($language): void { $this->isChanged('language', $language); $this->language = $language; @@ -347,7 +357,7 @@ public function generateNameForChildObject(string $entityType, int $entityId, Cu /** * @param CustomFieldValueInterface $customFieldValue */ - public function addCustomFieldValue($customFieldValue) + public function addCustomFieldValue($customFieldValue): void { if (null === $this->customFieldValues) { $this->customFieldValues = new ArrayCollection(); @@ -361,13 +371,13 @@ public function addCustomFieldValue($customFieldValue) * * @throws NotFoundException */ - public function setCustomFieldValues($values) + public function setCustomFieldValues($values): void { foreach ($values as $fieldName => $fieldValue) { try { $customFieldValue = $this->findCustomFieldValueForFieldAlias((string) $fieldName); $customFieldValue->setValue($fieldValue); - } catch (NotFoundException $e) { + } catch (NotFoundException) { $this->createNewCustomFieldValueByFieldAlias((string) $fieldName, $fieldValue); } } @@ -377,7 +387,7 @@ public function setCustomFieldValues($values) /** * Called when the custom field values are loaded from the database. */ - public function createFieldValuesSnapshot() + public function createFieldValuesSnapshot(): void { foreach ($this->customFieldValues as $customFieldValue) { $this->initialCustomFieldValues[$customFieldValue->getCustomField()->getId()] = $customFieldValue->getValue(); @@ -387,7 +397,7 @@ public function createFieldValuesSnapshot() /** * Called before CustomItemSave. It will record changes that happened for custom field values. */ - public function recordCustomFieldValueChanges() + public function recordCustomFieldValueChanges(): void { foreach ($this->customFieldValues as $customFieldValue) { $customFieldId = $customFieldValue->getCustomField()->getId(); @@ -446,11 +456,20 @@ public function setFieldValues(array $values): void try { $customFieldValue = $this->findCustomFieldValueForFieldId((int) $value['id']); $customFieldValue->setValue($value['value']); - } catch (NotFoundException $e) { + } catch (NotFoundException) { $this->createNewCustomFieldValueByFieldId((int) $value['id'], $value['value']); } } - $this->setDefaultValuesForMissingFields(); + + /** + * We could have done it in CustomItemDataPersister::persist() by + * injecting Symfony\Component\HttpFoundation\RequestStack and get request method. + * Since, CustomItem entity has multiple public methods which could lead to BC break. + * Hence, we are using $_SERVER here to get the request method type. + */ + if ('PATCH' !== $_SERVER['REQUEST_METHOD']) { + $this->setDefaultValuesForMissingFields(); + } } /** @@ -480,9 +499,10 @@ public function findCustomFieldValueForFieldId($customFieldId) */ public function findCustomFieldValueForFieldAlias($customFieldAlias) { - $filteredValues = $this->customFieldValues->filter(function (CustomFieldValueInterface $customFieldValue) use ($customFieldAlias) { - return $customFieldValue->getCustomField()->getAlias() === $customFieldAlias; - }); + $filteredValues = $this->customFieldValues->filter( + function (CustomFieldValueInterface $customFieldValue) use ($customFieldAlias): bool { + return $customFieldValue->getCustomField()->getAlias() === $customFieldAlias; + }); if (!$filteredValues->count()) { throw new NotFoundException("Custom Field Value for alias = {$customFieldAlias} was not found."); @@ -495,7 +515,7 @@ public function findChildCustomItem(): CustomItem { /** @var CustomItemXrefCustomItem|null $childXref */ $childXref = $this->getCustomItemLowerReferences() - ->filter(function (CustomItemXrefCustomItem $xref) { + ->filter(function (CustomItemXrefCustomItem $xref): bool { // The child custom item's object must have the same ID as the current custom item child object. return $xref->getCustomItemLinkedTo($this)->getCustomObject()->getMasterObject()->getId() === $this->getCustomObject()->getId(); })->first(); @@ -551,10 +571,10 @@ public function createNewCustomFieldValueByFieldAlias(string $customFieldAlias, public function setDefaultValuesForMissingFields(): void { - $this->getCustomObject()->getCustomFields()->map(function (CustomField $customField) { + $this->getCustomObject()->getCustomFields()->map(function (CustomField $customField): void { try { $this->findCustomFieldValueForFieldId($customField->getId()); - } catch (NotFoundException $e) { + } catch (NotFoundException) { $this->addCustomFieldValue( $customField->getTypeObject()->createValueEntity($customField, $this, $customField->getDefaultValue()) ); @@ -565,7 +585,7 @@ public function setDefaultValuesForMissingFields(): void /** * @param CustomItemXrefInterface $reference */ - public function addContactReference($reference) + public function addContactReference($reference): void { $this->contactReferences->add($reference); } @@ -581,7 +601,7 @@ public function getContactReferences() /** * @param CustomItemXrefInterface $reference */ - public function addCompanyReference($reference) + public function addCompanyReference($reference): void { $this->companyReferences->add($reference); } @@ -597,7 +617,7 @@ public function getCompanyReferences() /** * @param CustomItemXrefInterface $reference */ - public function addCustomItemReference($reference) + public function addCustomItemReference($reference): void { $this->customItemLowerReferences->add($reference); } @@ -612,16 +632,12 @@ public function getCustomItemLowerReferences() public function getRelationsByType(string $entityType): Collection { - switch ($entityType) { - case 'contact': - return $this->getContactReferences(); - case 'company': - return $this->getCompanyReferences(); - case 'customItem': - return $this->getCustomItemLowerReferences(); - default: - return new ArrayCollection([]); - } + return match ($entityType) { + 'contact' => $this->getContactReferences(), + 'company' => $this->getCompanyReferences(), + 'customItem' => $this->getCustomItemLowerReferences(), + default => new ArrayCollection([]), + }; } public function getUniqueHash(): ?string @@ -649,7 +665,7 @@ public function updateUniqueHash(): void $uniqueIdentifierFieldAlias = $uniqueIdentifierField->getAlias(); $uniqueHash[$uniqueIdentifierFieldAlias] = $this->findCustomFieldValueForFieldAlias($uniqueIdentifierFieldAlias)->getValue(); } - //To prevent creation of duplicates (in case of multiple unique ID fields) due to the order of key-values in the array + // To prevent creation of duplicates (in case of multiple unique ID fields) due to the order of key-values in the array // Eg. {id => 1, name => "Jay"} and {name => "Jay", id => 1} are duplicates ksort($uniqueHash); diff --git a/Entity/CustomItemExportScheduler.php b/Entity/CustomItemExportScheduler.php index 78eedde11..0f135048a 100644 --- a/Entity/CustomItemExportScheduler.php +++ b/Entity/CustomItemExportScheduler.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Entity; -use DateTimeImmutable; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping\ClassMetadata; use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder; @@ -19,7 +18,7 @@ class CustomItemExportScheduler private User $user; // Created by - private DateTimeImmutable $scheduledDateTime; + private \DateTimeImmutable $scheduledDateTime; private int $customObjectId; @@ -78,12 +77,12 @@ public function setUser(User $user): self return $this; } - public function getScheduledDateTime(): ?DateTimeImmutable + public function getScheduledDateTime(): ?\DateTimeImmutable { return $this->scheduledDateTime; } - public function setScheduledDateTime(DateTimeImmutable $scheduledDateTime): self + public function setScheduledDateTime(\DateTimeImmutable $scheduledDateTime): self { $this->scheduledDateTime = $scheduledDateTime; $this->addChange('scheduledDateTime', $scheduledDateTime); diff --git a/Entity/CustomItemXrefCompany.php b/Entity/CustomItemXrefCompany.php index 659f0b267..8d03163f3 100644 --- a/Entity/CustomItemXrefCompany.php +++ b/Entity/CustomItemXrefCompany.php @@ -4,10 +4,7 @@ namespace MauticPlugin\CustomObjectsBundle\Entity; -use DateTimeImmutable; -use DateTimeInterface; -use DateTimeZone; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder; use Mautic\LeadBundle\Entity\Company; @@ -17,26 +14,14 @@ class CustomItemXrefCompany implements CustomItemXrefInterface public const TABLE_NAME = 'custom_item_xref_company'; public const TABLE_ALIAS = 'CustomItemXrefCompany'; - /** - * @var Company - */ - private $company; - - /** - * @var CustomItem - */ - private $customItem; + private \DateTimeInterface $dateAdded; - /** - * @var DateTimeInterface - */ - private $dateAdded; - - public function __construct(CustomItem $customItem, Company $company, ?DateTimeInterface $dateAdded = null) - { - $this->customItem = $customItem; - $this->company = $company; - $this->dateAdded = $dateAdded ?: new DateTimeImmutable('now', new DateTimeZone('UTC')); + public function __construct( + private CustomItem $customItem, + private Company $company, + ?\DateTimeInterface $dateAdded = null + ) { + $this->dateAdded = $dateAdded ?: new \DateTimeImmutable('now', new \DateTimeZone('UTC')); } public static function loadMetadata(ORM\ClassMetadata $metadata): void @@ -58,7 +43,7 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void ->fetchExtraLazy() ->build(); - $builder->createField('dateAdded', Type::DATETIME) + $builder->createField('dateAdded', Types::DATETIME_MUTABLE) ->columnName('date_added') ->build(); } @@ -88,7 +73,7 @@ public function getLinkedEntity() } /** - * @return DateTimeInterface + * @return \DateTimeInterface */ public function getDateAdded() { diff --git a/Entity/CustomItemXrefContact.php b/Entity/CustomItemXrefContact.php index 6f6b88a71..0648a0ea7 100644 --- a/Entity/CustomItemXrefContact.php +++ b/Entity/CustomItemXrefContact.php @@ -4,10 +4,7 @@ namespace MauticPlugin\CustomObjectsBundle\Entity; -use DateTimeImmutable; -use DateTimeInterface; -use DateTimeZone; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder; use Mautic\LeadBundle\Entity\Lead; @@ -18,26 +15,14 @@ class CustomItemXrefContact implements CustomItemXrefInterface public const TABLE_NAME = 'custom_item_xref_contact'; public const TABLE_ALIAS = 'CustomItemXrefContact'; - /** - * @var Lead - */ - private $contact; - - /** - * @var CustomItem - */ - private $customItem; + private \DateTimeInterface $dateAdded; - /** - * @var DateTimeInterface - */ - private $dateAdded; - - public function __construct(CustomItem $customItem, Lead $contact, ?DateTimeInterface $dateAdded = null) - { - $this->customItem = $customItem; - $this->contact = $contact; - $this->dateAdded = $dateAdded ?: new DateTimeImmutable('now', new DateTimeZone('UTC')); + public function __construct( + private CustomItem $customItem, + private Lead $contact, + ?\DateTimeInterface $dateAdded = null + ) { + $this->dateAdded = $dateAdded ?: new \DateTimeImmutable('now', new \DateTimeZone('UTC')); } public static function loadMetadata(ORM\ClassMetadata $metadata): void @@ -60,7 +45,7 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void ->fetchExtraLazy() ->build(); - $builder->createField('dateAdded', Type::DATETIME) + $builder->createField('dateAdded', Types::DATETIME_MUTABLE) ->columnName('date_added') ->build(); } @@ -90,7 +75,7 @@ public function getLinkedEntity() } /** - * @return DateTimeInterface + * @return \DateTimeInterface */ public function getDateAdded() { diff --git a/Entity/CustomItemXrefCustomItem.php b/Entity/CustomItemXrefCustomItem.php index c447ca596..d60730d5b 100644 --- a/Entity/CustomItemXrefCustomItem.php +++ b/Entity/CustomItemXrefCustomItem.php @@ -4,14 +4,10 @@ namespace MauticPlugin\CustomObjectsBundle\Entity; -use DateTimeImmutable; -use DateTimeInterface; -use DateTimeZone; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemXrefCustomItemRepository; -use UnexpectedValueException; /** * As the {custom item} - {custom item} table can store the IDs both ways (higher - lower, lower - higher) @@ -25,28 +21,19 @@ class CustomItemXrefCustomItem implements CustomItemXrefInterface { public const TABLE_ALIAS = 'CustomItemXrefCustomItem'; - /** - * @var CustomItem - */ - private $customItemLower; + private CustomItem $customItemLower; - /** - * @var CustomItem - */ - private $customItemHigher; + private CustomItem $customItemHigher; - /** - * @var DateTimeInterface - */ - private $dateAdded; + private \DateTimeInterface $dateAdded; /** - * @throws UnexpectedValueException + * @throws \UnexpectedValueException */ - public function __construct(CustomItem $customItemA, CustomItem $customItemB, ?DateTimeInterface $dateAdded = null) + public function __construct(CustomItem $customItemA, CustomItem $customItemB, ?\DateTimeInterface $dateAdded = null) { if ($customItemA->getId() && $customItemA->getId() === $customItemB->getId()) { - throw new UnexpectedValueException('It is not possible to link identical custom item.'); + throw new \UnexpectedValueException('It is not possible to link identical custom item.'); } if ($customItemA->getId() < $customItemB->getId()) { @@ -57,7 +44,7 @@ public function __construct(CustomItem $customItemA, CustomItem $customItemB, ?D $this->customItemHigher = $customItemA; } - $this->dateAdded = $dateAdded ?: new DateTimeImmutable('now', new DateTimeZone('UTC')); + $this->dateAdded = $dateAdded ?: new \DateTimeImmutable('now', new \DateTimeZone('UTC')); } public static function loadMetadata(ORM\ClassMetadata $metadata): void @@ -80,7 +67,7 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void ->fetchExtraLazy() ->build(); - $builder->createField('dateAdded', Type::DATETIME) + $builder->createField('dateAdded', Types::DATETIME_MUTABLE) ->columnName('date_added') ->build(); } @@ -118,7 +105,7 @@ public function getCustomItemHigher() } /** - * @return DateTimeInterface + * @return \DateTimeInterface */ public function getDateAdded() { diff --git a/Entity/CustomItemXrefInterface.php b/Entity/CustomItemXrefInterface.php index 1f99dbb1c..8452d1bb8 100644 --- a/Entity/CustomItemXrefInterface.php +++ b/Entity/CustomItemXrefInterface.php @@ -4,8 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Entity; -use DateTimeInterface; - interface CustomItemXrefInterface { /** @@ -19,7 +17,7 @@ public function getCustomItem(); public function getLinkedEntity(); /** - * @return DateTimeInterface + * @return \DateTimeInterface */ public function getDateAdded(); } diff --git a/Entity/CustomObject.php b/Entity/CustomObject.php index bc35327a6..8f2c8a210 100644 --- a/Entity/CustomObject.php +++ b/Entity/CustomObject.php @@ -8,7 +8,7 @@ use ApiPlatform\Core\Annotation\ApiResource; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; -use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping\JoinColumn; use Doctrine\ORM\Mapping\OneToOne; @@ -31,7 +31,6 @@ * }, * itemOperations={ * "get"={"security"="'custom_objects:custom_objects:view'"}, - * "put"={"security"="'custom_objects:custom_objects:edit'"}, * "patch"={"security"="'custom_objects:custom_objects:edit'"}, * "delete"={"security"="'custom_objects:custom_objects:delete'"} * }, @@ -51,7 +50,9 @@ class CustomObject extends FormEntity implements UniqueEntityInterface /** * @var int|null + * * @Groups({"custom_object:read"}) + * * @ApiProperty( * attributes={ * "openapi_context"={ @@ -66,66 +67,82 @@ class CustomObject extends FormEntity implements UniqueEntityInterface /** * @var string|null + * * @Groups({"custom_object:read", "custom_object:write"}) */ private $alias; /** * @var string|null + * * @Groups({"custom_object:read", "custom_object:write"}) */ private $nameSingular; /** * @var string|null + * * @Groups({"custom_object:read", "custom_object:write"}) */ private $namePlural; /** * @var string|null + * * @Groups({"custom_object:read", "custom_object:write"}) */ private $description; /** * @var string|null + * * @Groups({"custom_object:read", "custom_object:write"}) */ private $language; /** * @var Category|null + * * @Assert\Valid **/ private $category; /** * @var ArrayCollection + * * @Groups({"custom_object:read", "custom_object:write"}) */ private $customFields; /** * @var int|null + * * @Groups({"custom_object:read", "custom_object:write"}) */ private $type = self::TYPE_MASTER; /** * @var CustomObject|null + * * @OneToOne(targetEntity="CustomObject") + * * @JoinColumn(name="master_object", referencedColumnName="id") + * * @Groups({"custom_object:read", "custom_object:write"}) + * * @ApiProperty(readableLink=false, writableLink=false) */ private $masterObject; /** * @var CustomObject|null + * * @OneToOne(targetEntity="CustomObject") + * * @JoinColumn(name="relationship_object", referencedColumnName="id", onDelete="SET NULL") + * * @Groups({"custom_object:read", "custom_object:write"}) + * * @ApiProperty(readableLink=false, writableLink=false) */ private $relationshipObject; @@ -165,12 +182,12 @@ public static function loadMetadata(ORM\ClassMetadata $metadata): void $builder->addId(); $builder->addCategory(); - $builder->addField('alias', Type::STRING); - $builder->addNamedField('nameSingular', Type::STRING, 'name_singular'); - $builder->addNamedField('namePlural', Type::STRING, 'name_plural'); - $builder->addNullableField('description', Type::STRING, 'description'); - $builder->addNullableField('language', Type::STRING, 'lang'); - $builder->addNullableField('type', Type::INTEGER); + $builder->addField('alias', Types::STRING); + $builder->addNamedField('nameSingular', Types::STRING, 'name_singular'); + $builder->addNamedField('namePlural', Types::STRING, 'name_plural'); + $builder->addNullableField('description', Types::STRING, 'description'); + $builder->addNullableField('language', Types::STRING, 'lang'); + $builder->addNullableField('type', Types::INTEGER); $builder->createOneToOne('relationshipObject', CustomObject::class) ->addJoinColumn('relationship_object', 'id', true, false, 'SET NULL') @@ -221,7 +238,7 @@ public function getName() /** * @param string|null $alias */ - public function setAlias($alias) + public function setAlias($alias): void { $this->isChanged('alias', $alias); $this->alias = $alias; @@ -268,7 +285,7 @@ public function setRelationshipObject(?CustomObject $customObject): void /** * @param string|null $nameSingular */ - public function setNameSingular($nameSingular) + public function setNameSingular($nameSingular): void { $this->isChanged('nameSingular', $nameSingular); $this->nameSingular = $nameSingular; @@ -285,7 +302,7 @@ public function getNameSingular() /** * @param string|null $namePlural */ - public function setNamePlural($namePlural) + public function setNamePlural($namePlural): void { $this->isChanged('namePlural', $namePlural); $this->namePlural = $namePlural; @@ -302,7 +319,7 @@ public function getNamePlural() /** * @param string|null $description */ - public function setDescription($description) + public function setDescription($description): void { $this->isChanged('description', $description); $this->description = $description; @@ -327,7 +344,7 @@ public function getCategory() /** * @param Category|null $category */ - public function setCategory($category) + public function setCategory($category): void { $this->category = $category; } @@ -343,24 +360,24 @@ public function getLanguage() /** * @param string|null $language */ - public function setLanguage($language) + public function setLanguage($language): void { $this->isChanged('language', $language); $this->language = $language; } - public function addCustomField(CustomField $customField) + public function addCustomField(CustomField $customField): void { $customField->setCustomObject($this); $this->customFields->add($customField); } - public function setCustomFields(ArrayCollection $customFields) + public function setCustomFields(ArrayCollection $customFields): void { $this->customFields = $customFields; } - public function removeCustomField(CustomField $customField) + public function removeCustomField(CustomField $customField): void { $this->customFields->removeElement($customField); $customField->setCustomObject(); @@ -390,13 +407,13 @@ public function getCustomFieldByOrder($order) } } - throw new NotFoundException("Custom field with order index '${order}' not found."); + throw new NotFoundException('Custom field with order index '.$order.' not found.'); } public function getPublishedFields(): Collection { return $this->customFields->filter( - function (CustomField $customField) { + function (CustomField $customField): bool { return $customField->isPublished(); } ); @@ -405,7 +422,7 @@ function (CustomField $customField) { public function getFieldsShowInCustomObjectDetailList(): Collection { return $this->customFields->filter( - function (CustomField $customField) { + function (CustomField $customField): bool { return $customField->isShowInCustomObjectDetailList(); } ); @@ -414,7 +431,7 @@ function (CustomField $customField) { public function getFieldsShowInContactDetailList(): Collection { return $this->customFields->filter( - function (CustomField $customField) { + function (CustomField $customField): bool { return $customField->isShowInContactDetailList(); } ); @@ -423,15 +440,14 @@ function (CustomField $customField) { public function getUniqueIdentifierFields(): ?ArrayCollection { return $this->customFields->filter( - static fn(CustomField $customField) => $customField->getIsUniqueIdentifier() + static fn (CustomField $customField) => $customField->getIsUniqueIdentifier() ); } - /** * Called when the custom fields are loaded from the database. */ - public function createFieldsSnapshot() + public function createFieldsSnapshot(): void { foreach ($this->customFields as $customField) { $this->initialCustomFields[$customField->getId()] = $customField->toArray(); @@ -441,7 +457,7 @@ public function createFieldsSnapshot() /** * Called before CustomObjectSave. It will record changes that happened for custom fields. */ - public function recordCustomFieldChanges() + public function recordCustomFieldChanges(): void { $existingFields = []; foreach ($this->customFields as $i => $customField) { diff --git a/Event/CustomItemEvent.php b/Event/CustomItemEvent.php index 152ff9ee6..e44334fbe 100644 --- a/Event/CustomItemEvent.php +++ b/Event/CustomItemEvent.php @@ -5,24 +5,12 @@ namespace MauticPlugin\CustomObjectsBundle\Event; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; class CustomItemEvent extends Event { - /** - * @var CustomItem - */ - private $customItem; - - /** - * @var bool - */ - private $isNew; - - public function __construct(CustomItem $customItem, bool $isNew = false) + public function __construct(private CustomItem $customItem, private bool $isNew = false) { - $this->customItem = $customItem; - $this->isNew = $isNew; } public function getCustomItem(): CustomItem diff --git a/Event/CustomItemExportSchedulerEvent.php b/Event/CustomItemExportSchedulerEvent.php index d2164e986..0ac3da983 100644 --- a/Event/CustomItemExportSchedulerEvent.php +++ b/Event/CustomItemExportSchedulerEvent.php @@ -5,17 +5,14 @@ namespace MauticPlugin\CustomObjectsBundle\Event; use MauticPlugin\CustomObjectsBundle\Entity\CustomItemExportScheduler; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; class CustomItemExportSchedulerEvent extends Event { - private CustomItemExportScheduler $customItemExportScheduler; - private string $filePath; - public function __construct(CustomItemExportScheduler $customItemExportScheduler) + public function __construct(private CustomItemExportScheduler $customItemExportScheduler) { - $this->customItemExportScheduler = $customItemExportScheduler; } public function getCustomItemExportScheduler(): CustomItemExportScheduler diff --git a/Event/CustomItemListDbalQueryEvent.php b/Event/CustomItemListDbalQueryEvent.php index 02c74d38c..fd38ee435 100644 --- a/Event/CustomItemListDbalQueryEvent.php +++ b/Event/CustomItemListDbalQueryEvent.php @@ -6,24 +6,12 @@ use Doctrine\DBAL\Query\QueryBuilder; use MauticPlugin\CustomObjectsBundle\DTO\TableConfig; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; class CustomItemListDbalQueryEvent extends Event { - /** - * @var QueryBuilder - */ - private $queryBuilder; - - /** - * @var TableConfig - */ - private $tableConfig; - - public function __construct(QueryBuilder $queryBuilder, TableConfig $tableConfig) + public function __construct(private QueryBuilder $queryBuilder, private TableConfig $tableConfig) { - $this->queryBuilder = $queryBuilder; - $this->tableConfig = $tableConfig; } public function getQueryBuilder(): QueryBuilder diff --git a/Event/CustomItemListQueryEvent.php b/Event/CustomItemListQueryEvent.php index fb6943993..78f06e662 100644 --- a/Event/CustomItemListQueryEvent.php +++ b/Event/CustomItemListQueryEvent.php @@ -6,24 +6,14 @@ use Doctrine\ORM\QueryBuilder; use MauticPlugin\CustomObjectsBundle\DTO\TableConfig; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; class CustomItemListQueryEvent extends Event { - /** - * @var QueryBuilder - */ - private $queryBuilder; - - /** - * @var TableConfig - */ - private $tableConfig; - - public function __construct(QueryBuilder $queryBuilder, TableConfig $tableConfig) - { - $this->queryBuilder = $queryBuilder; - $this->tableConfig = $tableConfig; + public function __construct( + private QueryBuilder $queryBuilder, + private TableConfig $tableConfig + ) { } public function getQueryBuilder(): QueryBuilder diff --git a/Event/CustomItemXrefEntityDiscoveryEvent.php b/Event/CustomItemXrefEntityDiscoveryEvent.php index b55024fb5..8e6d4ce81 100644 --- a/Event/CustomItemXrefEntityDiscoveryEvent.php +++ b/Event/CustomItemXrefEntityDiscoveryEvent.php @@ -6,35 +6,17 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefInterface; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; class CustomItemXrefEntityDiscoveryEvent extends Event { - /** - * @var CustomItem - */ - private $customItem; + private ?CustomItemXrefInterface $customItemXrefEntity = null; - /** - * @var string - */ - private $entityType; - - /** - * @var int - */ - private $entityId; - - /** - * @var CustomItemXrefInterface|null - */ - private $customItemXrefEntity; - - public function __construct(CustomItem $customItem, string $entityType, int $entityId) - { - $this->customItem = $customItem; - $this->entityType = $entityType; - $this->entityId = $entityId; + public function __construct( + private CustomItem $customItem, + private string $entityType, + private int $entityId + ) { } public function getCustomItem(): CustomItem @@ -57,9 +39,6 @@ public function setXrefEntity(CustomItemXrefInterface $customItemXrefEntity): vo $this->customItemXrefEntity = $customItemXrefEntity; } - /** - * @return ?CustomItemXrefInterface - */ public function getXrefEntity(): ?CustomItemXrefInterface { return $this->customItemXrefEntity; diff --git a/Event/CustomItemXrefEntityEvent.php b/Event/CustomItemXrefEntityEvent.php index 3981c9fb4..e7195978c 100644 --- a/Event/CustomItemXrefEntityEvent.php +++ b/Event/CustomItemXrefEntityEvent.php @@ -5,18 +5,12 @@ namespace MauticPlugin\CustomObjectsBundle\Event; use MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefInterface; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; class CustomItemXrefEntityEvent extends Event { - /** - * @var CustomItemXrefInterface - */ - private $xRef; - - public function __construct(CustomItemXrefInterface $xRef) + public function __construct(private CustomItemXrefInterface $xRef) { - $this->xRef = $xRef; } public function getXref(): CustomItemXrefInterface diff --git a/Event/CustomObjectEvent.php b/Event/CustomObjectEvent.php index d37f1e43d..7e8acb8f9 100644 --- a/Event/CustomObjectEvent.php +++ b/Event/CustomObjectEvent.php @@ -6,34 +6,16 @@ use Mautic\CoreBundle\Service\FlashBag; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; class CustomObjectEvent extends Event { - /** - * @var CustomObject - */ - private $customObject; + private string $message; - /** - * @var bool - */ - private $isNew; + private FlashBag $flashBag; - /** - * @var string - */ - private $message; - - /** - * @var FlashBag - */ - private $flashBag; - - public function __construct(CustomObject $customObject, bool $isNew = false) + public function __construct(private CustomObject $customObject, private bool $isNew = false) { - $this->customObject = $customObject; - $this->isNew = $isNew; } public function getCustomObject(): CustomObject diff --git a/Event/CustomObjectListFormatEvent.php b/Event/CustomObjectListFormatEvent.php index 257c95941..ef2433240 100644 --- a/Event/CustomObjectListFormatEvent.php +++ b/Event/CustomObjectListFormatEvent.php @@ -4,34 +4,16 @@ namespace MauticPlugin\CustomObjectsBundle\Event; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Contracts\EventDispatcher\Event; class CustomObjectListFormatEvent extends Event { - /** - * @var array - */ - private $customObjectValues; + private string $formattedString = ''; - /** - * @var string - */ - private $format; + private bool $hasBeenFormatted = false; - /** - * @var string - */ - private $formattedString = ''; - - /** - * @var bool - */ - private $hasBeenFormatted = false; - - public function __construct(array $customObjectValues, string $format = 'default') + public function __construct(private array $customObjectValues, private string $format = 'default') { - $this->customObjectValues = $customObjectValues; - $this->format = $format; } public function getCustomObjectValues(): array diff --git a/EventListener/ApiSubscriber.php b/EventListener/ApiSubscriber.php index 472846d1f..7125f145d 100644 --- a/EventListener/ApiSubscriber.php +++ b/EventListener/ApiSubscriber.php @@ -4,9 +4,9 @@ namespace MauticPlugin\CustomObjectsBundle\EventListener; -use InvalidArgumentException; use Mautic\ApiBundle\ApiEvents; use Mautic\ApiBundle\Event\ApiEntityEvent; +use Mautic\LeadBundle\Controller\Api\LeadApiController; use Mautic\LeadBundle\Entity\Lead; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; @@ -21,29 +21,11 @@ class ApiSubscriber implements EventSubscriberInterface { - /** - * @var ConfigProvider - */ - private $configProvider; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomItemModel - */ - private $customItemModel; - public function __construct( - ConfigProvider $configProvider, - CustomObjectModel $customObjectModel, - CustomItemModel $customItemModel + private ConfigProvider $configProvider, + private CustomObjectModel $customObjectModel, + private CustomItemModel $customItemModel ) { - $this->configProvider = $configProvider; - $this->customObjectModel = $customObjectModel; - $this->customItemModel = $customItemModel; } /** @@ -78,7 +60,7 @@ private function saveCustomItems(ApiEntityEvent $event, bool $dryRun = false): v $event->getEntityRequestParameters(), $event->getRequest() ); - } catch (InvalidArgumentException $e) { + } catch (\InvalidArgumentException) { return; } @@ -111,20 +93,20 @@ private function saveCustomItems(ApiEntityEvent $event, bool $dryRun = false): v * * @return mixed[] * - * @throws InvalidArgumentException + * @throws \InvalidArgumentException */ private function getCustomObjectsFromContactCreateRequest(array $entityRequestParameters, Request $request): array { if (!$this->configProvider->pluginIsEnabled()) { - throw new InvalidArgumentException('Custom Object Plugin is disabled'); + throw new \InvalidArgumentException('Custom Object Plugin is disabled'); } - if (1 !== preg_match('/^\/api\/contacts\/.*(new|edit)/', $request->getPathInfo())) { - throw new InvalidArgumentException('Not a API request we care about'); + if (1 !== preg_match('~^'.preg_quote(LeadApiController::class, '~').'(::|:)(new|edit)(Entity|Entities)Action$~i', $request->attributes->get('_controller'))) { + throw new \InvalidArgumentException('Not a API request we care about'); } if (empty($entityRequestParameters['customObjects']['data']) || !is_array($entityRequestParameters['customObjects']['data'])) { - throw new InvalidArgumentException('The request payload does not contain any custom items in the customObjects attribute.'); + throw new \InvalidArgumentException('The request payload does not contain any custom items in the customObjects attribute.'); } return $entityRequestParameters['customObjects']; @@ -133,7 +115,7 @@ private function getCustomObjectsFromContactCreateRequest(array $entityRequestPa /** * @param mixed[] $customObjectData * - * @throws NotFoundException|InvalidArgumentException + * @throws NotFoundException|\InvalidArgumentException */ private function getCustomObject(array $customObjectData): CustomObject { @@ -144,7 +126,7 @@ private function getCustomObject(array $customObjectData): CustomObject return $this->customObjectModel->fetchEntityByAlias($customObjectData['alias']); } - throw new InvalidArgumentException('customObject[data][][id] or customObject[data][][alias] must exist in the request to identify a Custom Object.', Response::HTTP_BAD_REQUEST); + throw new \InvalidArgumentException('customObject[data][][id] or customObject[data][][alias] must exist in the request to identify a Custom Object.', Response::HTTP_BAD_REQUEST); } catch (NotFoundException $e) { throw new NotFoundException($e->getMessage(), Response::HTTP_BAD_REQUEST, $e); } diff --git a/EventListener/AssetsSubscriber.php b/EventListener/AssetsSubscriber.php index 997431a27..0b5e7e264 100644 --- a/EventListener/AssetsSubscriber.php +++ b/EventListener/AssetsSubscriber.php @@ -4,31 +4,19 @@ namespace MauticPlugin\CustomObjectsBundle\EventListener; -use Mautic\CoreBundle\Templating\Helper\AssetsHelper; +use Mautic\CoreBundle\Twig\Helper\AssetsHelper; use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\KernelEvents; class AssetsSubscriber implements EventSubscriberInterface { - /** - * @var AssetsHelper - */ - private $assetHelper; - - /** - * @var ConfigProvider - */ - private $configProvider; - public function __construct( - AssetsHelper $assetHelper, - ConfigProvider $configProvider + private AssetsHelper $assetHelper, + private ConfigProvider $configProvider ) { - $this->assetHelper = $assetHelper; - $this->configProvider = $configProvider; } /** @@ -41,9 +29,9 @@ public static function getSubscribedEvents(): array ]; } - public function loadAssets(GetResponseEvent $event): void + public function loadAssets(RequestEvent $event): void { - if ($this->configProvider->pluginIsEnabled() && $event->isMasterRequest() && $this->isMauticAdministrationPage($event->getRequest())) { + if ($this->configProvider->pluginIsEnabled() && $event->isMainRequest() && $this->isMauticAdministrationPage($event->getRequest())) { $this->assetHelper->addScript('plugins/CustomObjectsBundle/Assets/js/custom-objects.js'); $this->assetHelper->addScript('plugins/CustomObjectsBundle/Assets/js/co-form.js'); $this->assetHelper->addStylesheet('plugins/CustomObjectsBundle/Assets/css/custom-objects.css'); diff --git a/EventListener/AuditLogSubscriber.php b/EventListener/AuditLogSubscriber.php index 8290ca51b..1dc86ebc0 100644 --- a/EventListener/AuditLogSubscriber.php +++ b/EventListener/AuditLogSubscriber.php @@ -15,20 +15,10 @@ class AuditLogSubscriber implements EventSubscriberInterface { - /** - * @var AuditLogModel - */ - private $auditLogModel; - - /** - * @var IpLookupHelper - */ - private $ipLookupHelper; - - public function __construct(AuditLogModel $auditLogModel, IpLookupHelper $ipLookupHelper) - { - $this->auditLogModel = $auditLogModel; - $this->ipLookupHelper = $ipLookupHelper; + public function __construct( + private AuditLogModel $auditLogModel, + private IpLookupHelper $ipLookupHelper + ) { } /** diff --git a/EventListener/CampaignSubscriber.php b/EventListener/CampaignSubscriber.php index 706ff2670..01e437e79 100644 --- a/EventListener/CampaignSubscriber.php +++ b/EventListener/CampaignSubscriber.php @@ -5,7 +5,7 @@ namespace MauticPlugin\CustomObjectsBundle\EventListener; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Exception; use Doctrine\DBAL\Query\QueryBuilder; use Mautic\CampaignBundle\CampaignEvents; use Mautic\CampaignBundle\Event\CampaignBuilderEvent; @@ -16,7 +16,6 @@ use MauticPlugin\CustomObjectsBundle\CustomItemEvents; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; -use MauticPlugin\CustomObjectsBundle\Exception\InvalidArgumentException; use MauticPlugin\CustomObjectsBundle\Exception\InvalidSegmentFilterException; use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; use MauticPlugin\CustomObjectsBundle\Form\Type\CampaignActionLinkType; @@ -31,71 +30,23 @@ use MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\QueryFilterFactory; use MauticPlugin\CustomObjectsBundle\Segment\Query\UnionQueryContainer; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CampaignSubscriber implements EventSubscriberInterface { use DbalQueryTrait; use QueryBuilderManipulatorTrait; - /** - * @var TranslatorInterface - */ - private $translator; - - /** - * @var CustomFieldModel - */ - private $customFieldModel; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var ConfigProvider - */ - private $configProvider; - - /** - * @var QueryFilterHelper - */ - private $queryFilterHelper; - - /** - * @var QueryFilterFactory - */ - private $queryFilterFactory; - - /** - * @var Connection - */ - private $connection; - public function __construct( - CustomFieldModel $customFieldModel, - CustomObjectModel $customObjectModel, - CustomItemModel $customItemModel, - TranslatorInterface $translator, - ConfigProvider $configProvider, - QueryFilterHelper $queryFilterHelper, - QueryFilterFactory $queryFilterFactory, - Connection $connection + private CustomFieldModel $customFieldModel, + private CustomObjectModel $customObjectModel, + private CustomItemModel $customItemModel, + private TranslatorInterface $translator, + private ConfigProvider $configProvider, + private QueryFilterHelper $queryFilterHelper, + private QueryFilterFactory $queryFilterFactory, + private Connection $connection ) { - $this->customFieldModel = $customFieldModel; - $this->customObjectModel = $customObjectModel; - $this->customItemModel = $customItemModel; - $this->translator = $translator; - $this->configProvider = $configProvider; - $this->queryFilterHelper = $queryFilterHelper; - $this->queryFilterFactory = $queryFilterFactory; - $this->connection = $connection; } /** @@ -140,8 +91,8 @@ public function onCampaignBuild(CampaignBuilderEvent $event): void 'description' => $this->translator->trans('custom.item.events.field.value_descr', ['%customObject%' => $customObject->getNameSingular()]), 'eventName' => CustomItemEvents::ON_CAMPAIGN_TRIGGER_CONDITION, 'formType' => CampaignConditionFieldValueType::class, - 'formTheme' => 'CustomObjectsBundle:FormTheme\FieldValueCondition', - 'formTypeOptions' => ['customObject' => $customObject], + 'formTheme' => '@MauticForm/FormTheme/FieldValueCondition/_campaignevent_form_field_value_widget.html.twig', + 'formTypeOptions' => ['customObjectId' => $customObject->getId()], ]); } } @@ -165,7 +116,7 @@ public function onCampaignTriggerAction(CampaignExecutionEvent $event): void try { $customItem = $this->customItemModel->fetchEntity($linkCustomItemId); $this->customItemModel->linkEntity($customItem, 'contact', $contactId); - } catch (NotFoundException $e) { + } catch (NotFoundException) { // Do nothing if the custom item doesn't exist anymore. } } @@ -174,7 +125,7 @@ public function onCampaignTriggerAction(CampaignExecutionEvent $event): void try { $customItem = $this->customItemModel->fetchEntity($unlinkCustomItemId); $this->customItemModel->unlinkEntity($customItem, 'contact', $contactId); - } catch (NotFoundException $e) { + } catch (NotFoundException) { // Do nothing if the custom item doesn't exist anymore. } } @@ -182,9 +133,7 @@ public function onCampaignTriggerAction(CampaignExecutionEvent $event): void /** * @throws NotFoundException - * @throws DBALException - * @throws InvalidArgumentException - * @throws InvalidSegmentFilterException + * @throws InvalidSegmentFilterException|Exception */ public function onCampaignTriggerCondition(CampaignExecutionEvent $event): void { @@ -206,7 +155,7 @@ public function onCampaignTriggerCondition(CampaignExecutionEvent $event): void try { $customField = $this->customFieldModel->fetchEntity((int) $event->getConfig()['field']); - } catch (NotFoundException $e) { + } catch (NotFoundException) { $event->setResult(false); return; @@ -221,14 +170,14 @@ public function onCampaignTriggerCondition(CampaignExecutionEvent $event): void ); if ($innerQueryBuilder instanceof UnionQueryContainer) { - $this->applyParamsToMultipleQueries($innerQueryBuilder, $queryAlias, $contact, $operator); + $this->applyParamsToMultipleQueries($innerQueryBuilder, $queryAlias, $contact); } else { - $this->applyParamsToQuery($innerQueryBuilder, $queryAlias, $contact, $operator); + $this->applyParamsToQuery($innerQueryBuilder, $queryAlias, $contact); } $queryBuilder = $this->buildOuterQuery($innerQueryBuilder, $queryAlias); - $customItemId = $this->executeSelect($queryBuilder)->fetchColumn(); + $customItemId = $this->executeSelect($queryBuilder)->fetchOne(); if ($customItemId) { $event->setChannel('customItem', $customItemId); @@ -238,14 +187,14 @@ public function onCampaignTriggerCondition(CampaignExecutionEvent $event): void } } - private function applyParamsToMultipleQueries(UnionQueryContainer $unionQueryContainer, string $queryAlias, Lead $contact, string $operator): void + private function applyParamsToMultipleQueries(UnionQueryContainer $unionQueryContainer, string $queryAlias, Lead $contact): void { foreach ($unionQueryContainer as $segmentQueryBuilder) { - $this->applyParamsToQuery($segmentQueryBuilder, $queryAlias, $contact, $operator); + $this->applyParamsToQuery($segmentQueryBuilder, $queryAlias, $contact); } } - private function applyParamsToQuery(SegmentQueryBuilder $innerQueryBuilder, string $queryAlias, Lead $contact, string $operator): void + private function applyParamsToQuery(SegmentQueryBuilder $innerQueryBuilder, string $queryAlias, Lead $contact): void { $innerQueryBuilder->select($queryAlias.'_value.custom_item_id'); $this->queryFilterHelper->addContactIdRestriction($innerQueryBuilder, $queryAlias, (int) $contact->getId()); diff --git a/EventListener/ContactSubscriber.php b/EventListener/ContactSubscriber.php index 16e27da98..24cf17c35 100644 --- a/EventListener/ContactSubscriber.php +++ b/EventListener/ContactSubscriber.php @@ -7,54 +7,28 @@ use Doctrine\ORM\EntityManager; use Mautic\LeadBundle\Entity\LeadEventLog; use Mautic\LeadBundle\Entity\LeadEventLogRepository; +use Mautic\LeadBundle\Event\LeadMergeEvent; use Mautic\LeadBundle\Event\LeadTimelineEvent; use Mautic\LeadBundle\LeadEvents; +use MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefContact; use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; +use MauticPlugin\CustomObjectsBundle\Repository\CustomItemXrefContactRepository; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ContactSubscriber implements EventSubscriberInterface { - /** - * @var TranslatorInterface - */ - private $translator; - - /** - * @var EntityManager - */ - private $entityManager; - - /** - * @var CustomItemRouteProvider - */ - private $routeProvider; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var ConfigProvider - */ - private $configProvider; - public function __construct( - EntityManager $entityManager, - TranslatorInterface $translator, - CustomItemRouteProvider $routeProvider, - CustomItemModel $customItemModel, - ConfigProvider $configProvider + private EntityManager $entityManager, + private TranslatorInterface $translator, + private CustomItemRouteProvider $routeProvider, + private CustomItemModel $customItemModel, + private ConfigProvider $configProvider, + private CustomItemXrefContactRepository $customItemXrefContactRepository ) { - $this->entityManager = $entityManager; - $this->translator = $translator; - $this->routeProvider = $routeProvider; - $this->customItemModel = $customItemModel; - $this->configProvider = $configProvider; } /** @@ -64,6 +38,7 @@ public static function getSubscribedEvents(): array { return [ LeadEvents::TIMELINE_ON_GENERATE => 'onTimelineGenerate', + LeadEvents::LEAD_PRE_MERGE => 'onCongactPreMerge', ]; } @@ -99,6 +74,43 @@ public function onTimelineGenerate(LeadTimelineEvent $event): void } } + /** + * Moves the custom item links from the loser to the victor if they don't exist in the victor's list. + * Removes the remaining links from the loser. + */ + public function onCongactPreMerge(LeadMergeEvent $event): void + { + if (!$this->configProvider->pluginIsEnabled()) { + return; + } + + $loser = $event->getLoser(); + + /** @var CustomItemXrefContact[] $loserLinks */ + $loserLinks = $this->customItemXrefContactRepository->findBy(['contact' => $loser]); + + if (!$loserLinks) { + return; + } + + $victor = $event->getVictor(); + + /** @var CustomItemXrefContact[] $victorLinks */ + $victorLinks = $this->customItemXrefContactRepository->findBy(['contact' => $victor]); + $victorItemsIds = array_map(fn (CustomItemXrefContact $link) => $link->getCustomItem()->getId(), $victorLinks); + + foreach ($loserLinks as $loserLink) { + if (!in_array($loserLink->getCustomItem()->getId(), $victorItemsIds)) { + $newLink = new CustomItemXrefContact($loserLink->getCustomItem(), $victor, $loserLink->getDateAdded()); + $this->entityManager->persist($newLink); + } + + $this->entityManager->remove($loserLink); + } + + $this->entityManager->flush(); + } + /** * @return mixed[] */ @@ -130,7 +142,7 @@ private function addLinkTimelineEntry(LeadTimelineEvent $event, string $eventTyp 'label' => $this->translator->trans("custom.item.{$action}.event", ['%customItemName%' => $customItem->getName()]), 'href' => $this->routeProvider->buildViewRoute($customItem->getCustomObject()->getId(), $customItem->getId()), ]; - } catch (NotFoundException $e) { + } catch (NotFoundException) { $eventLabel = $this->translator->trans("custom.item.{$action}.event.not.found", ['%customItemId%' => $link['object_id']]); } $event->addEvent([ @@ -142,7 +154,7 @@ private function addLinkTimelineEntry(LeadTimelineEvent $event, string $eventTyp 'icon' => "fa-{$action}", 'extra' => $link, 'contactId' => $link['lead_id'], - 'contentTemplate' => 'CustomObjectsBundle:SubscribedEvents\Timeline:link.html.php', + 'contentTemplate' => '@CustomObjects/SubscribedEvents/Timeline/link.html.twig', ]); } } diff --git a/EventListener/ContactTabSubscriber.php b/EventListener/ContactTabSubscriber.php index 70ec02190..d2f78f032 100644 --- a/EventListener/ContactTabSubscriber.php +++ b/EventListener/ContactTabSubscriber.php @@ -14,59 +14,23 @@ use MauticPlugin\CustomObjectsBundle\Provider\SessionProviderFactory; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ContactTabSubscriber implements EventSubscriberInterface { - /** - * @var TranslatorInterface - */ - private $translator; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomItemRepository - */ - private $customItemRepository; - - /** - * @var ConfigProvider - */ - private $configProvider; - - /** - * @var CustomItemRouteProvider - */ - private $customItemRouteProvider; - /** * @var CustomObject[] */ - private $customObjects = []; - - /** - * @var SessionProviderFactory - */ - private $sessionProviderFactory; + private array $customObjects = []; public function __construct( - CustomObjectModel $customObjectModel, - CustomItemRepository $customItemRepository, - ConfigProvider $configProvider, - TranslatorInterface $translator, - CustomItemRouteProvider $customItemRouteProvider, - SessionProviderFactory $sessionProviderFactory + private CustomObjectModel $customObjectModel, + private CustomItemRepository $customItemRepository, + private ConfigProvider $configProvider, + private TranslatorInterface $translator, + private CustomItemRouteProvider $customItemRouteProvider, + private SessionProviderFactory $sessionProviderFactory ) { - $this->customObjectModel = $customObjectModel; - $this->customItemRepository = $customItemRepository; - $this->configProvider = $configProvider; - $this->translator = $translator; - $this->customItemRouteProvider = $customItemRouteProvider; - $this->sessionProviderFactory = $sessionProviderFactory; } /** @@ -85,7 +49,7 @@ public function injectTabs(CustomContentEvent $event): void return; } - if ($event->checkContext('MauticLeadBundle:Lead:lead.html.php', 'tabs')) { + if ($event->checkContext('@MauticLead/Lead/lead.html.twig', 'tabs')) { $vars = $event->getVars(); $objects = $this->customObjectModel->getMasterCustomObjects(); @@ -100,13 +64,13 @@ public function injectTabs(CustomContentEvent $event): void 'tabId' => "custom-object-{$object->getId()}", ]; - $event->addTemplate('CustomObjectsBundle:SubscribedEvents/Tab:link.html.php', $data); + $event->addTemplate('@CustomObjects/SubscribedEvents/Tab/link.html.twig', $data); } - $event->addTemplate('CustomObjectsBundle:SubscribedEvents/Tab:modal.html.php'); + $event->addTemplate('@CustomObjects/SubscribedEvents/Tab/modal.html.twig'); } - if ($event->checkContext('MauticLeadBundle:Lead:lead.html.php', 'tabs.content')) { + if ($event->checkContext('@MauticLead/Lead/lead.html.twig', 'tabs.content')) { $vars = $event->getVars(); $objects = $this->getCustomObjects(); @@ -133,7 +97,7 @@ public function injectTabs(CustomContentEvent $event): void 'namespace' => $sessionProvider->getNamespace(), ]; - $event->addTemplate('CustomObjectsBundle:SubscribedEvents/Tab:content.html.php', $data); + $event->addTemplate('@CustomObjects/SubscribedEvents/Tab/content.html.twig', $data); } } } diff --git a/EventListener/CustomFieldPostLoadSubscriber.php b/EventListener/CustomFieldPostLoadSubscriber.php index db8be307b..5f3b6699b 100644 --- a/EventListener/CustomFieldPostLoadSubscriber.php +++ b/EventListener/CustomFieldPostLoadSubscriber.php @@ -5,8 +5,8 @@ namespace MauticPlugin\CustomObjectsBundle\EventListener; use Doctrine\Common\EventSubscriber; -use Doctrine\ORM\Event\LifecycleEventArgs; use Doctrine\ORM\Events; +use Doctrine\Persistence\Event\LifecycleEventArgs; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider; @@ -16,14 +16,8 @@ */ class CustomFieldPostLoadSubscriber implements EventSubscriber { - /** - * @var CustomFieldTypeProvider - */ - private $customFieldTypeProvider; - - public function __construct(CustomFieldTypeProvider $customFieldTypeProvider) + public function __construct(private CustomFieldTypeProvider $customFieldTypeProvider) { - $this->customFieldTypeProvider = $customFieldTypeProvider; } /** diff --git a/EventListener/CustomFieldPreSaveSubscriber.php b/EventListener/CustomFieldPreSaveSubscriber.php index c168d7ff1..511e98035 100644 --- a/EventListener/CustomFieldPreSaveSubscriber.php +++ b/EventListener/CustomFieldPreSaveSubscriber.php @@ -16,17 +16,11 @@ */ class CustomFieldPreSaveSubscriber implements EventSubscriberInterface { - /** - * @var CustomFieldOptionModel - */ - private $customFieldOptionModel; - /** * CustomFieldPreSaveSubscriber constructor. */ - public function __construct(CustomFieldOptionModel $customFieldOptionModel) + public function __construct(private CustomFieldOptionModel $customFieldOptionModel) { - $this->customFieldOptionModel = $customFieldOptionModel; } /** diff --git a/EventListener/CustomItemButtonSubscriber.php b/EventListener/CustomItemButtonSubscriber.php index 5b2fdb61e..9ce55717f 100644 --- a/EventListener/CustomItemButtonSubscriber.php +++ b/EventListener/CustomItemButtonSubscriber.php @@ -6,39 +6,21 @@ use Mautic\CoreBundle\CoreEvents; use Mautic\CoreBundle\Event\CustomButtonEvent; -use Mautic\CoreBundle\Templating\Helper\ButtonHelper; +use Mautic\CoreBundle\Twig\Helper\ButtonHelper; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Exception\ForbiddenException; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomItemButtonSubscriber implements EventSubscriberInterface { - /** - * @var TranslatorInterface - */ - private $translator; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomItemRouteProvider - */ - private $routeProvider; - public function __construct( - CustomItemPermissionProvider $permissionProvider, - CustomItemRouteProvider $routeProvider, - TranslatorInterface $translator + private CustomItemPermissionProvider $permissionProvider, + private CustomItemRouteProvider $routeProvider, + private TranslatorInterface $translator ) { - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - $this->translator = $translator; } /** @@ -57,8 +39,8 @@ public function injectViewButtons(CustomButtonEvent $event): void case CustomItemRouteProvider::ROUTE_LIST: try { $customObjectId = $this->getCustomObjectIdFromEvent($event); - $filterEntityId = $event->getRequest()->query->get('filterEntityId', false); - $filterEntityType = $event->getRequest()->query->get('filterEntityType', false); + $filterEntityId = $event->getRequest()->query->get('filterEntityId'); + $filterEntityType = $event->getRequest()->query->get('filterEntityType'); $loadedInTab = (bool) $filterEntityId; if ($loadedInTab && in_array($filterEntityType, ['contact', 'customItem'], true)) { $customItem = $event->getItem(); @@ -112,7 +94,7 @@ public function injectViewButtons(CustomButtonEvent $event): void $event->getRoute() ); } - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { } break; @@ -136,17 +118,17 @@ private function addEntityButtons(CustomButtonEvent $event, string $location, in if ($customItem && $customItem instanceof CustomItem) { try { $event->addButton($this->defineDeleteButton($customObjectId, $customItem), $location, $event->getRoute()); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { } try { $event->addButton($this->defineCloneButton($customObjectId, $customItem), $location, $event->getRoute()); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { } try { $event->addButton($this->defineEditButton($customObjectId, $customItem), $location, $event->getRoute()); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { } } } @@ -295,7 +277,7 @@ private function defineLinkButton(int $customObjectId, CustomItem $customItem, s return [ 'attr' => [ 'href' => '#', - 'onclick' => "CustomObjects.linkCustomItemWithEntity(this, event, ${customObjectId}, '${entityType}', ${entityId}, 'custom-object-${customObjectId}', ".($relationshipObjectId ?: 'null').');', + 'onclick' => "CustomObjects.linkCustomItemWithEntity(this, event, {$customObjectId}, '{$entityType}', {$entityId}, 'custom-object-{$customObjectId}', ".($relationshipObjectId ?: 'null').');', 'data-action' => $action, 'data-toggle' => '', ], @@ -317,7 +299,7 @@ private function defineUnlinkButton(int $customObjectId, int $customItemId, stri return [ 'attr' => [ 'href' => '#', - 'onclick' => "CustomObjects.unlinkCustomItemFromEntity(this, event, ${customObjectId}, '${entityType}', ${entityId}, 'custom-object-${customObjectId}');", + 'onclick' => "CustomObjects.unlinkCustomItemFromEntity(this, event, {$customObjectId}, '{$entityType}', {$entityId}, 'custom-object-{$customObjectId}');", 'data-action' => $this->routeProvider->buildUnlinkRoute($customItemId, $entityType, $entityId), 'data-toggle' => '', ], diff --git a/EventListener/CustomItemPostDeleteSubscriber.php b/EventListener/CustomItemPostDeleteSubscriber.php index 7182a2d03..e94ec4e96 100644 --- a/EventListener/CustomItemPostDeleteSubscriber.php +++ b/EventListener/CustomItemPostDeleteSubscriber.php @@ -12,22 +12,10 @@ final class CustomItemPostDeleteSubscriber implements EventSubscriberInterface { - /** - * @var CustomItemXrefCustomItemRepository - */ - private $customItemXrefCustomItemRepository; - - /** - * @var CustomItemXrefContactRepository - */ - private $customItemXrefContactRepository; - public function __construct( - CustomItemXrefCustomItemRepository $customItemXrefCustomItemRepository, - CustomItemXrefContactRepository $customItemXrefContactRepository + private CustomItemXrefCustomItemRepository $customItemXrefCustomItemRepository, + private CustomItemXrefContactRepository $customItemXrefContactRepository ) { - $this->customItemXrefCustomItemRepository = $customItemXrefCustomItemRepository; - $this->customItemXrefContactRepository = $customItemXrefContactRepository; } public static function getSubscribedEvents() diff --git a/EventListener/CustomItemPostSaveSubscriber.php b/EventListener/CustomItemPostSaveSubscriber.php index fc590b7e5..f784bd8f1 100644 --- a/EventListener/CustomItemPostSaveSubscriber.php +++ b/EventListener/CustomItemPostSaveSubscriber.php @@ -14,20 +14,10 @@ class CustomItemPostSaveSubscriber implements EventSubscriberInterface { - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var RequestStack - */ - private $requestStack; - - public function __construct(CustomItemModel $customItemModel, RequestStack $requestStack) - { - $this->customItemModel = $customItemModel; - $this->requestStack = $requestStack; + public function __construct( + private CustomItemModel $customItemModel, + private RequestStack $requestStack + ) { } public static function getSubscribedEvents() diff --git a/EventListener/CustomItemScheduledExportSubscriber.php b/EventListener/CustomItemScheduledExportSubscriber.php index d9f372b43..b824ef210 100644 --- a/EventListener/CustomItemScheduledExportSubscriber.php +++ b/EventListener/CustomItemScheduledExportSubscriber.php @@ -11,11 +11,8 @@ class CustomItemScheduledExportSubscriber implements EventSubscriberInterface { - private CustomItemExportSchedulerModel $customItemExportSchedulerModel; - - public function __construct(CustomItemExportSchedulerModel $customItemExportSchedulerModel) + public function __construct(private CustomItemExportSchedulerModel $customItemExportSchedulerModel) { - $this->customItemExportSchedulerModel = $customItemExportSchedulerModel; } /** diff --git a/EventListener/CustomItemTabSubscriber.php b/EventListener/CustomItemTabSubscriber.php index b80a5feb0..18fa93fd1 100644 --- a/EventListener/CustomItemTabSubscriber.php +++ b/EventListener/CustomItemTabSubscriber.php @@ -13,52 +13,22 @@ use MauticPlugin\CustomObjectsBundle\Provider\SessionProviderFactory; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomItemTabSubscriber implements EventSubscriberInterface { - /** - * @var TranslatorInterface - */ - private $translator; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomItemRepository - */ - private $customItemRepository; - - /** - * @var CustomItemRouteProvider - */ - private $customItemRouteProvider; - /** * @var CustomObject[] */ - private $customObjects = []; - - /** - * @var SessionProviderFactory - */ - private $sessionProviderFactory; + private array $customObjects = []; public function __construct( - CustomObjectModel $customObjectModel, - CustomItemRepository $customItemRepository, - TranslatorInterface $translator, - CustomItemRouteProvider $customItemRouteProvider, - SessionProviderFactory $sessionProviderFactory + private CustomObjectModel $customObjectModel, + private CustomItemRepository $customItemRepository, + private TranslatorInterface $translator, + private CustomItemRouteProvider $customItemRouteProvider, + private SessionProviderFactory $sessionProviderFactory ) { - $this->customObjectModel = $customObjectModel; - $this->customItemRepository = $customItemRepository; - $this->translator = $translator; - $this->customItemRouteProvider = $customItemRouteProvider; - $this->sessionProviderFactory = $sessionProviderFactory; } /** @@ -73,7 +43,7 @@ public static function getSubscribedEvents(): array public function injectTabs(CustomContentEvent $event): void { - if ($event->checkContext('CustomObjectsBundle:CustomItem:detail.html.php', 'tabs')) { + if ($event->checkContext('@CustomObjects/CustomItem/detail.html.twig', 'tabs')) { $vars = $event->getVars(); $objects = $this->customObjectModel->getMasterCustomObjects(); @@ -92,13 +62,13 @@ public function injectTabs(CustomContentEvent $event): void 'tabId' => "custom-object-{$object->getId()}", ]; - $event->addTemplate('CustomObjectsBundle:SubscribedEvents/Tab:link.html.php', $data); + $event->addTemplate('@CustomObjects/SubscribedEvents/Tab/link.html.twig', $data); } - $event->addTemplate('CustomObjectsBundle:SubscribedEvents/Tab:modal.html.php'); + $event->addTemplate('@CustomObjects/SubscribedEvents/Tab/modal.html.twig'); } - if ($event->checkContext('CustomObjectsBundle:CustomItem:detail.html.php', 'tabs.content')) { + if ($event->checkContext('@CustomObjects/CustomItem/detail.html.twig', 'tabs.content')) { $vars = $event->getVars(); $objects = $this->getCustomObjects(); @@ -129,7 +99,7 @@ public function injectTabs(CustomContentEvent $event): void 'namespace' => $sessionProvider->getNamespace(), ]; - $event->addTemplate('CustomObjectsBundle:SubscribedEvents/Tab:content.html.php', $data); + $event->addTemplate('@CustomObjects/SubscribedEvents/Tab/content.html.twig', $data); } } } diff --git a/EventListener/CustomItemXrefContactSubscriber.php b/EventListener/CustomItemXrefContactSubscriber.php index 57fb4c18d..b47ca0fd0 100644 --- a/EventListener/CustomItemXrefContactSubscriber.php +++ b/EventListener/CustomItemXrefContactSubscriber.php @@ -25,29 +25,11 @@ class CustomItemXrefContactSubscriber implements EventSubscriberInterface { - /** - * @var EntityManager - */ - private $entityManager; - - /** - * @var UserHelper - */ - private $userHelper; - - /** - * @var CustomItemRepository - */ - private $customItemRepository; - public function __construct( - EntityManager $entityManager, - UserHelper $userHelper, - CustomItemRepository $customItemRepository + private EntityManager $entityManager, + private UserHelper $userHelper, + private CustomItemRepository $customItemRepository ) { - $this->entityManager = $entityManager; - $this->userHelper = $userHelper; - $this->customItemRepository = $customItemRepository; } /** @@ -118,7 +100,7 @@ public function onEntityLinkDiscovery(CustomItemXrefEntityDiscoveryEvent $event) if ('contact' === $event->getEntityType()) { try { $xRef = $this->getContactXrefEntity($event->getCustomItem()->getId(), $event->getEntityId()); - } catch (NoResultException $e) { + } catch (NoResultException) { /** @var Lead $contact */ $contact = $this->entityManager->getReference(Lead::class, $event->getEntityId()); $xRef = new CustomItemXrefContact($event->getCustomItem(), $contact); diff --git a/EventListener/CustomItemXrefCustomItemSubscriber.php b/EventListener/CustomItemXrefCustomItemSubscriber.php index 4f1599a72..cfefa82ae 100644 --- a/EventListener/CustomItemXrefCustomItemSubscriber.php +++ b/EventListener/CustomItemXrefCustomItemSubscriber.php @@ -17,24 +17,13 @@ use MauticPlugin\CustomObjectsBundle\Event\CustomItemXrefEntityEvent; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use UnexpectedValueException; class CustomItemXrefCustomItemSubscriber implements EventSubscriberInterface { - /** - * @var EntityManager - */ - private $entityManager; - - /** - * @var CustomItemRepository - */ - private $customItemRepository; - - public function __construct(EntityManager $entityManager, CustomItemRepository $customItemRepository) - { - $this->entityManager = $entityManager; - $this->customItemRepository = $customItemRepository; + public function __construct( + private EntityManager $entityManager, + private CustomItemRepository $customItemRepository + ) { } /** @@ -81,7 +70,7 @@ public function onLookupQuery(CustomItemListQueryEvent $event): void } /** - * @throws UnexpectedValueException + * @throws \UnexpectedValueException * @throws ORMException */ public function onEntityLinkDiscovery(CustomItemXrefEntityDiscoveryEvent $event): void @@ -89,7 +78,7 @@ public function onEntityLinkDiscovery(CustomItemXrefEntityDiscoveryEvent $event) if ('customItem' === $event->getEntityType()) { try { $xRef = $this->getXrefEntity($event->getCustomItem()->getId(), $event->getEntityId()); - } catch (NoResultException $e) { + } catch (NoResultException) { /** @var CustomItem $customItemB */ $customItemB = $this->entityManager->getReference(CustomItem::class, $event->getEntityId()); $xRef = new CustomItemXrefCustomItem($event->getCustomItem(), $customItemB); diff --git a/EventListener/CustomObjectButtonSubscriber.php b/EventListener/CustomObjectButtonSubscriber.php index 63d801a70..1e68d13c3 100644 --- a/EventListener/CustomObjectButtonSubscriber.php +++ b/EventListener/CustomObjectButtonSubscriber.php @@ -6,7 +6,7 @@ use Mautic\CoreBundle\CoreEvents; use Mautic\CoreBundle\Event\CustomButtonEvent; -use Mautic\CoreBundle\Templating\Helper\ButtonHelper; +use Mautic\CoreBundle\Twig\Helper\ButtonHelper; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Exception\ForbiddenException; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; @@ -14,47 +14,17 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectRouteProvider; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomObjectButtonSubscriber implements EventSubscriberInterface { - /** - * @var CustomObjectPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomObjectRouteProvider - */ - private $routeProvider; - - /** - * @var CustomItemPermissionProvider - */ - private $customItemPermissionProvider; - - /** - * @var CustomItemRouteProvider - */ - private $customItemRouteProvider; - - /** - * @var TranslatorInterface - */ - private $translator; - public function __construct( - CustomObjectPermissionProvider $permissionProvider, - CustomObjectRouteProvider $routeProvider, - CustomItemPermissionProvider $customItemPermissionProvider, - CustomItemRouteProvider $customItemRouteProvider, - TranslatorInterface $translator + private CustomObjectPermissionProvider $permissionProvider, + private CustomObjectRouteProvider $routeProvider, + private CustomItemPermissionProvider $customItemPermissionProvider, + private CustomItemRouteProvider $customItemRouteProvider, + private TranslatorInterface $translator ) { - $this->permissionProvider = $permissionProvider; - $this->routeProvider = $routeProvider; - $this->customItemPermissionProvider = $customItemPermissionProvider; - $this->customItemRouteProvider = $customItemRouteProvider; - $this->translator = $translator; } /** @@ -75,7 +45,7 @@ public function injectViewButtons(CustomButtonEvent $event): void try { $event->addButton($this->defineNewButton(), ButtonHelper::LOCATION_PAGE_ACTIONS, $event->getRoute()); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { } break; @@ -89,12 +59,12 @@ public function injectViewButtons(CustomButtonEvent $event): void if ($customObject) { try { $event->addButton($this->defineViewCustomItemsButton($customObject), ButtonHelper::LOCATION_PAGE_ACTIONS, $event->getRoute()); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { } try { $event->addButton($this->defineCreateNewCustomItemButton($customObject), ButtonHelper::LOCATION_PAGE_ACTIONS, $event->getRoute()); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { } } @@ -108,17 +78,17 @@ private function addEntityButtons(CustomButtonEvent $event, string $location): v if ($entity && $entity instanceof CustomObject) { try { $event->addButton($this->defineDeleteButton($entity), $location, $event->getRoute()); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { } try { $event->addButton($this->defineCloneButton($entity), $location, $event->getRoute()); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { } try { $event->addButton($this->defineEditButton($entity), $location, $event->getRoute()); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { } } } diff --git a/EventListener/CustomObjectListFormatSubscriber.php b/EventListener/CustomObjectListFormatSubscriber.php index 4baf4de19..5eec8ea3b 100644 --- a/EventListener/CustomObjectListFormatSubscriber.php +++ b/EventListener/CustomObjectListFormatSubscriber.php @@ -11,14 +11,8 @@ class CustomObjectListFormatSubscriber implements EventSubscriberInterface { - /** - * @var TokenFormatter - */ - private $tokenFormatter; - - public function __construct(TokenFormatter $tokenFormatter) + public function __construct(private TokenFormatter $tokenFormatter) { - $this->tokenFormatter = $tokenFormatter; } public static function getSubscribedEvents(): array diff --git a/EventListener/CustomObjectPostSaveSubscriber.php b/EventListener/CustomObjectPostSaveSubscriber.php index ee08c9166..db7cf4c8d 100644 --- a/EventListener/CustomObjectPostSaveSubscriber.php +++ b/EventListener/CustomObjectPostSaveSubscriber.php @@ -12,14 +12,8 @@ class CustomObjectPostSaveSubscriber implements EventSubscriberInterface { - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - public function __construct(CustomObjectModel $customObjectModel) + public function __construct(private CustomObjectModel $customObjectModel) { - $this->customObjectModel = $customObjectModel; } public static function getSubscribedEvents() diff --git a/EventListener/CustomObjectPreDeleteSubscriber.php b/EventListener/CustomObjectPreDeleteSubscriber.php index 75df9122a..f711b251e 100644 --- a/EventListener/CustomObjectPreDeleteSubscriber.php +++ b/EventListener/CustomObjectPreDeleteSubscriber.php @@ -8,24 +8,14 @@ use MauticPlugin\CustomObjectsBundle\Event\CustomObjectEvent; use MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomObjectPreDeleteSubscriber implements EventSubscriberInterface { - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var TranslatorInterface - */ - private $translator; - - public function __construct(CustomObjectModel $customObjectModel, TranslatorInterface $translator) - { - $this->customObjectModel = $customObjectModel; - $this->translator = $translator; + public function __construct( + private CustomObjectModel $customObjectModel, + private TranslatorInterface $translator + ) { } public static function getSubscribedEvents() diff --git a/EventListener/DynamicContentSubscriber.php b/EventListener/DynamicContentSubscriber.php index 6487fba6d..dbef2642d 100644 --- a/EventListener/DynamicContentSubscriber.php +++ b/EventListener/DynamicContentSubscriber.php @@ -6,57 +6,23 @@ use Mautic\DynamicContentBundle\DynamicContentEvents; use Mautic\DynamicContentBundle\Event\ContactFiltersEvaluateEvent; -use Mautic\EmailBundle\EventListener\MatchFilterForLeadTrait; -use MauticPlugin\CustomObjectsBundle\Exception\InvalidArgumentException; use MauticPlugin\CustomObjectsBundle\Exception\InvalidSegmentFilterException; -use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; -use MauticPlugin\CustomObjectsBundle\Helper\QueryFilterHelper; +use MauticPlugin\CustomObjectsBundle\Helper\ContactFilterMatcher; use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; -use MauticPlugin\CustomObjectsBundle\Repository\DbalQueryTrait; use MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\QueryFilterFactory; -use PDOException; -use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class DynamicContentSubscriber implements EventSubscriberInterface { - use MatchFilterForLeadTrait; - use DbalQueryTrait; - - /** - * @var QueryFilterFactory - */ - private $queryFilterFactory; - - /** - * @var QueryFilterHelper - */ - private $queryFilterHelper; - - /** - * @var ConfigProvider - */ - private $configProvider; - - /** - * @var LoggerInterface - */ - private $logger; - public function __construct( - QueryFilterFactory $queryFilterFactory, - QueryFilterHelper $queryFilterHelper, - ConfigProvider $configProvider, - LoggerInterface $logger + private QueryFilterFactory $queryFilterFactory, + private ContactFilterMatcher $contactFilterMatcher, + private ConfigProvider $configProvider, ) { - $this->queryFilterFactory = $queryFilterFactory; - $this->queryFilterHelper = $queryFilterHelper; - $this->configProvider = $configProvider; - $this->logger = $logger; } /** - * @return mixed[] + * @return array */ public static function getSubscribedEvents(): array { @@ -65,47 +31,38 @@ public static function getSubscribedEvents(): array ]; } - /** - * @throws InvalidArgumentException - * @throws NotFoundException - */ public function evaluateFilters(ContactFiltersEvaluateEvent $event): void { - if (!$this->configProvider->pluginIsEnabled()) { + if ($event->isEvaluated() + || !$this->configProvider->pluginIsEnabled() + || !$this->hasCustomObjectFilters($event->getFilters()) + ) { return; } - $eventFilters = $event->getFilters(); - - if ($event->isEvaluated()) { - return; - } - - foreach ($eventFilters as $key => $eventFilter) { - $queryAlias = "filter_{$key}"; - - try { - $filterQueryBuilder = $this->queryFilterFactory->configureQueryBuilderFromSegmentFilter($eventFilter, $queryAlias); - } catch (InvalidSegmentFilterException $e) { - continue; - } - - $this->queryFilterHelper->addContactIdRestriction($filterQueryBuilder, $queryAlias, (int) $event->getContact()->getId()); + $event->setIsEvaluated(true); + $event->stopPropagation(); + $contact = $event->getContact(); + $event->setIsMatched($this->contactFilterMatcher->match( + $event->getFilters(), + array_merge(['id' => $contact->getId()], $contact->getProfileFields()) + )); + } + /** + * @param mixed[] $filters + */ + private function hasCustomObjectFilters(array $filters): bool + { + foreach ($filters as $filter) { try { - if ($this->executeSelect($filterQueryBuilder)->rowCount()) { - $event->setIsEvaluated(true); - $event->setIsMatched(true); - } else { - $event->setIsEvaluated(true); - } - } catch (PDOException $e) { - $this->logger->addError('Failed to evaluate dynamic content for custom object '.$e->getMessage()); + $this->queryFilterFactory->configureQueryBuilderFromSegmentFilter($filter, 'filter'); - throw $e; + return true; + } catch (InvalidSegmentFilterException) { } - - $event->stopPropagation(); // The filter is ours, we won't allow no more processing } + + return false; } } diff --git a/EventListener/FilterOperatorSubscriber.php b/EventListener/FilterOperatorSubscriber.php index ff9d25221..d8b0c09e1 100644 --- a/EventListener/FilterOperatorSubscriber.php +++ b/EventListener/FilterOperatorSubscriber.php @@ -21,14 +21,8 @@ class FilterOperatorSubscriber implements EventSubscriberInterface public const NOT_IN_CUSTOM_OBJECTS = 'notInCustomObjects'; - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - public function __construct(CustomObjectModel $customObjectModel) + public function __construct(private CustomObjectModel $customObjectModel) { - $this->customObjectModel = $customObjectModel; } /** @@ -45,7 +39,7 @@ public static function getSubscribedEvents(): array ]; } - public function onOperatorsGenerate(LeadListFiltersOperatorsEvent $event) + public function onOperatorsGenerate(LeadListFiltersOperatorsEvent $event): void { $event->addOperator(self::WITHIN_CUSTOM_OBJECTS, [ 'label' => 'custom.within.custom.objects.label', @@ -121,9 +115,9 @@ public function onWithinFieldValuesBuilder(SegmentOperatorQueryBuilderEvent $eve ); } elseif ($event->operatorIsOneOf(self::NOT_IN_CUSTOM_OBJECTS)) { $queryBuilder = $event->getQueryBuilder(); - $subQueryBuilder = $queryBuilder->getConnection()->createQueryBuilder(); - $expr = $subQueryBuilder->expr(); - $customItemQueryBuilder = $subQueryBuilder->select('ci.name') + // $subQueryBuilder = $queryBuilder->getConnection()->createQueryBuilder(); + $expr = $queryBuilder->expr(); + $customItemQueryBuilder = $queryBuilder->select('ci.name') ->from(MAUTIC_TABLE_PREFIX.'custom_item', 'ci') ->andWhere($expr->eq('ci.custom_object_id', $customObjectId)) ->andWhere($expr->eq('ci.is_published', 1)); diff --git a/EventListener/ImportSubscriber.php b/EventListener/ImportSubscriber.php index 98fba5826..51bf22026 100644 --- a/EventListener/ImportSubscriber.php +++ b/EventListener/ImportSubscriber.php @@ -10,6 +10,7 @@ use Mautic\LeadBundle\Event\ImportProcessEvent; use Mautic\LeadBundle\Event\ImportValidateEvent; use Mautic\LeadBundle\LeadEvents; +use MauticPlugin\CustomObjectsBundle\DTO\ImportLogDTO; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Exception\ForbiddenException; use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; @@ -20,56 +21,20 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; use MauticPlugin\CustomObjectsBundle\Repository\CustomFieldRepository; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\Form; use Symfony\Component\Form\FormError; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\Form\FormInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ImportSubscriber implements EventSubscriberInterface { - /** - * @var TranslatorInterface - */ - private $translator; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomItemImportModel - */ - private $customItemImportModel; - - /** - * @var ConfigProvider - */ - private $configProvider; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomFieldRepository - */ - private $customFieldRepository; - public function __construct( - CustomObjectModel $customObjectModel, - CustomItemImportModel $customItemImportModel, - ConfigProvider $configProvider, - CustomItemPermissionProvider $permissionProvider, - CustomFieldRepository $customFieldRepository, - TranslatorInterface $translator + private CustomObjectModel $customObjectModel, + private CustomItemImportModel $customItemImportModel, + private ConfigProvider $configProvider, + private CustomItemPermissionProvider $permissionProvider, + private CustomFieldRepository $customFieldRepository, + private TranslatorInterface $translator ) { - $this->customObjectModel = $customObjectModel; - $this->customItemImportModel = $customItemImportModel; - $this->configProvider = $configProvider; - $this->permissionProvider = $permissionProvider; - $this->customFieldRepository = $customFieldRepository; - $this->translator = $translator; } /** @@ -101,7 +66,7 @@ public function onImportInit(ImportInitEvent $event): void $event->activeLink = "#mautic_custom_object_$customObjectId"; $event->setIndexRoute(CustomItemRouteProvider::ROUTE_LIST, ['objectId' => $customObjectId]); $event->stopPropagation(); - } catch (NotFoundException|ForbiddenException $e) { + } catch (NotFoundException|ForbiddenException) { } } @@ -133,7 +98,7 @@ public function onFieldMapping(ImportMappingEvent $event): void $customObject->getNamePlural() => $fieldList, 'mautic.lead.special_fields' => $specialFields, ]; - } catch (NotFoundException|ForbiddenException $e) { + } catch (NotFoundException|ForbiddenException) { } } @@ -145,7 +110,7 @@ public function onValidateImport(ImportValidateEvent $event): void try { $customObjectId = $this->getCustomObjectId($event->getRouteObjectName()); - } catch (NotFoundException $e) { + } catch (NotFoundException) { // This is not a Custom Object import. Abort. return; } @@ -162,7 +127,7 @@ public function onValidateImport(ImportValidateEvent $event): void if (empty($matchedFields)) { $form->addError( new FormError( - $this->translator->trans('mautic.lead.import.matchfields', [], 'validators') + $this->translator->trans('mautic.lead.import.matchfields', [], 'validators') ?? '' ) ); @@ -187,9 +152,14 @@ public function onImportProcess(ImportProcessEvent $event): void $customObjectId = $this->getCustomObjectId($event->import->getObject()); $this->permissionProvider->canCreate($customObjectId); $customObject = $this->customObjectModel->fetchEntity($customObjectId); - $merged = $this->customItemImportModel->import($event->import, $event->rowData, $customObject); + $importLogDto = new ImportLogDTO(); + $merged = $this->customItemImportModel->import($event->import, $event->rowData, $customObject, $importLogDto); $event->setWasMerged($merged); - } catch (NotFoundException $e) { + + if ($importLogDto->hasWarning()) { + $event->addWarning($importLogDto->getWarningsAsString()); + } + } catch (NotFoundException) { // Not a Custom Object import or the custom object doesn't exist anymore. Move on. } } @@ -223,13 +193,13 @@ private function handleValidateOwner(array $matchedFields): ?int * * @param mixed[] $matchedFields */ - private function handleValidateRequired(Form $form, int $customObjectId, array $matchedFields): void + private function handleValidateRequired(FormInterface $form, int $customObjectId, array $matchedFields): void { $requiredFields = $this->customFieldRepository->getRequiredCustomFieldsForCustomObject($customObjectId); - $missingRequiredFields = $requiredFields->filter(function (CustomField $customField) use ($matchedFields) { + $missingRequiredFields = $requiredFields->filter(function (CustomField $customField) use ($matchedFields): bool { return !array_key_exists($customField->getAlias(), $matchedFields); - })->map(function (CustomField $customField) { + })->map(function (CustomField $customField): string { return "{$customField->getLabel()} ({$customField->getAlias()})"; }); diff --git a/EventListener/MenuSubscriber.php b/EventListener/MenuSubscriber.php index 83ee2bb5c..f0e7a9d70 100644 --- a/EventListener/MenuSubscriber.php +++ b/EventListener/MenuSubscriber.php @@ -14,20 +14,8 @@ class MenuSubscriber implements EventSubscriberInterface { - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var ConfigProvider - */ - private $configProvider; - - public function __construct(CustomObjectModel $customObjectModel, ConfigProvider $configProvider) + public function __construct(private CustomObjectModel $customObjectModel, private ConfigProvider $configProvider) { - $this->customObjectModel = $customObjectModel; - $this->configProvider = $configProvider; } /** diff --git a/EventListener/ReportSubscriber.php b/EventListener/ReportSubscriber.php index 49bf3b71c..80229bfff 100644 --- a/EventListener/ReportSubscriber.php +++ b/EventListener/ReportSubscriber.php @@ -18,7 +18,7 @@ use MauticPlugin\CustomObjectsBundle\Report\ReportColumnsBuilder; use MauticPlugin\CustomObjectsBundle\Repository\CustomObjectRepository; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ReportSubscriber implements EventSubscriberInterface { @@ -35,43 +35,15 @@ class ReportSubscriber implements EventSubscriberInterface public const USERS_TABLE_ALIAS = 'u'; public const COMPANIES_TABLE_ALIAS = 'comp'; - /** - * @var ArrayCollection - */ - private $customObjects; - - /** - * @var CustomObjectRepository - */ - private $customObjectRepository; - - /** - * @var FieldsBuilder - */ - private $fieldsBuilder; - - /** - * @var CompanyReportData - */ - private $companyReportData; - - /** - * @var ReportHelper - */ - private $reportHelper; - - /** - * @var TranslatorInterface - */ - private $translator; + private ?ArrayCollection $customObjects = null; - public function __construct(CustomObjectRepository $customObjectRepository, FieldsBuilder $fieldsBuilder, CompanyReportData $companyReportData, ReportHelper $reportHelper, TranslatorInterface $translator) - { - $this->customObjectRepository = $customObjectRepository; - $this->fieldsBuilder = $fieldsBuilder; - $this->companyReportData = $companyReportData; - $this->reportHelper = $reportHelper; - $this->translator = $translator; + public function __construct( + private CustomObjectRepository $customObjectRepository, + private FieldsBuilder $fieldsBuilder, + private CompanyReportData $companyReportData, + private ReportHelper $reportHelper, + private TranslatorInterface $translator + ) { } private function getCustomObjects(): ArrayCollection @@ -90,10 +62,8 @@ private function getCustomObjects(): ArrayCollection foreach ($parentCustomObjects as $parentCustomObject) { $this->customObjects->add($parentCustomObject); $childCustomObject = $allCustomObjects->filter(function (CustomObject $childCustomObject) use ($parentCustomObject): bool { - return $childCustomObject->getMasterObject() ? - $parentCustomObject->getId() === $childCustomObject->getMasterObject()->getId() - : - false; + return $childCustomObject->getMasterObject() && $parentCustomObject->getId() + === $childCustomObject->getMasterObject()->getId(); })->first(); if (!$childCustomObject) { @@ -133,13 +103,16 @@ private function getContext(CustomObject $customObject): string private function getContexts(): array { return $this->getCustomObjects() - ->map(function (CustomObject $customObject) { + ->map(function (CustomObject $customObject): string { return $this->getContext($customObject); }) ->toArray(); } - private function getStandardColumns(string $prefix) + /** + * @return mixed[] + */ + private function getStandardColumns(string $prefix): array { return $this->reportHelper->getStandardColumns($prefix, ['description', 'publish_up', 'publish_down']); } @@ -148,7 +121,7 @@ private function addPrefixToColumnLabel(array $columns, string $prefix): array { foreach ($columns as $alias => $column) { $columnLabel = $this->translator->trans($columns[$alias]['label']); - if (0 === strpos($columnLabel, $prefix)) { + if (str_starts_with($columnLabel, $prefix)) { $columns[$alias]['label'] = $columnLabel; // Don't add the prefix twice continue; diff --git a/EventListener/SegmentFilterDecoratorDelegateSubscriber.php b/EventListener/SegmentFilterDecoratorDelegateSubscriber.php index ccd6ae9a6..6d8048aac 100644 --- a/EventListener/SegmentFilterDecoratorDelegateSubscriber.php +++ b/EventListener/SegmentFilterDecoratorDelegateSubscriber.php @@ -11,14 +11,8 @@ class SegmentFilterDecoratorDelegateSubscriber implements EventSubscriberInterface { - /** - * @var MultiselectDecorator - */ - private $multiselectDecorator; - - public function __construct(MultiselectDecorator $multiselectDecorator) + public function __construct(private MultiselectDecorator $multiselectDecorator) { - $this->multiselectDecorator = $multiselectDecorator; } /** diff --git a/EventListener/SegmentFiltersChoicesGenerateSubscriber.php b/EventListener/SegmentFiltersChoicesGenerateSubscriber.php index 2d9bb0564..66d26dda3 100644 --- a/EventListener/SegmentFiltersChoicesGenerateSubscriber.php +++ b/EventListener/SegmentFiltersChoicesGenerateSubscriber.php @@ -8,6 +8,7 @@ use Mautic\LeadBundle\Entity\OperatorListTrait; use Mautic\LeadBundle\Event\LeadListFiltersChoicesEvent; use Mautic\LeadBundle\LeadEvents; +use Mautic\LeadBundle\Provider\TypeOperatorProviderInterface; use MauticPlugin\CustomObjectsBundle\CustomFieldType\HiddenType; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; @@ -15,42 +16,25 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider; use MauticPlugin\CustomObjectsBundle\Repository\CustomObjectRepository; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class SegmentFiltersChoicesGenerateSubscriber implements EventSubscriberInterface { use OperatorListTrait; - /** - * @var CustomObjectRepository - */ - private $customObjectRepository; - /** * @var TranslatorInterface */ private $translator; - /** - * @var ConfigProvider - */ - private $configProvider; - - /** - * @var CustomFieldTypeProvider - */ - private $fieldTypeProvider; - public function __construct( - CustomObjectRepository $customObjectRepository, + private CustomObjectRepository $customObjectRepository, TranslatorInterface $translator, - ConfigProvider $configProvider, - CustomFieldTypeProvider $fieldTypeProvider + private ConfigProvider $configProvider, + private CustomFieldTypeProvider $fieldTypeProvider, + private TypeOperatorProviderInterface $typeOperatorProvider ) { - $this->customObjectRepository = $customObjectRepository; - $this->translator = $translator; - $this->configProvider = $configProvider; - $this->fieldTypeProvider = $fieldTypeProvider; + $this->translator = $translator; } /** @@ -79,21 +63,31 @@ function (CustomObject $customObject) use ($event, $fieldTypes): void { [ 'label' => $customObject->getName().' '.$this->translator->trans('custom.item.name.label'), 'properties' => ['type' => 'text'], - 'operators' => $this->getOperatorsForFieldType('text'), + 'operators' => $this->typeOperatorProvider->getOperatorsForFieldType('text'), 'object' => $customObject->getId(), ] ); /** @var CustomField $customField */ foreach ($customObject->getCustomFields()->getIterator() as $customField) { - if ($customField->getType() === $fieldTypes[HiddenType::NAME]) { // We don't want to show hidden types in filter list + if ($customField->getType() === $fieldTypes[HiddenType::NAME]) { + // We don't want to show hidden types in filter list continue; } - $allowedOperators = $customField->getTypeObject()->getOperators(); - $availableOperators = array_flip($this->getOperatorsForFieldType($customField->getType())); - $operators = array_intersect_key($availableOperators, $allowedOperators); - $operators = array_flip($operators); + if (method_exists($this->typeOperatorProvider, 'getContext') + && 'segment' === $this->typeOperatorProvider->getContext() + && method_exists($customField->getTypeObject(), 'getOperatorsForSegment') + ) { + $allowedOperators = $customField->getTypeObject()->getOperatorsForSegment(); + } else { + $allowedOperators = $customField->getTypeObject()->getOperators(); + } + + $typeOperators = $this->typeOperatorProvider->getOperatorsForFieldType($customField->getType()); + $availableOperators = array_flip($typeOperators); + $operators = array_intersect_key($availableOperators, $allowedOperators); + $operators = array_flip($operators); $event->addChoice( 'custom_object', diff --git a/EventListener/SegmentFiltersDictionarySubscriber.php b/EventListener/SegmentFiltersDictionarySubscriber.php index 98dd245e9..12b2b4a7c 100644 --- a/EventListener/SegmentFiltersDictionarySubscriber.php +++ b/EventListener/SegmentFiltersDictionarySubscriber.php @@ -4,8 +4,9 @@ namespace MauticPlugin\CustomObjectsBundle\EventListener; -use Doctrine\Bundle\DoctrineBundle\Registry; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception; +use Doctrine\Persistence\ManagerRegistry; use Mautic\LeadBundle\Event\SegmentDictionaryGenerationEvent; use Mautic\LeadBundle\LeadEvents; use Mautic\LeadBundle\Segment\Query\QueryBuilder; @@ -13,26 +14,17 @@ use MauticPlugin\CustomObjectsBundle\Repository\DbalQueryTrait; use MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\CustomFieldFilterQueryBuilder; use MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\CustomItemNameFilterQueryBuilder; +use MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\CustomObjectMergedFilterQueryBuilder; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class SegmentFiltersDictionarySubscriber implements EventSubscriberInterface { use DbalQueryTrait; - /** - * @var Registry - */ - private $doctrineRegistry; - - /** - * @var ConfigProvider - */ - private $configProvider; - - public function __construct(Registry $registry, ConfigProvider $configProvider) - { - $this->doctrineRegistry = $registry; - $this->configProvider = $configProvider; + public function __construct( + private ManagerRegistry $doctrineRegistry, + private ConfigProvider $configProvider + ) { } /** @@ -46,7 +38,7 @@ public static function getSubscribedEvents(): array } /** - * @throws \Doctrine\DBAL\DBALException + * @throws Exception */ public function onGenerateSegmentDictionary(SegmentDictionaryGenerationEvent $event): void { @@ -64,21 +56,28 @@ public function onGenerateSegmentDictionary(SegmentDictionaryGenerationEvent $ev ->from(MAUTIC_TABLE_PREFIX.'custom_object', 'o') ->leftJoin('o', MAUTIC_TABLE_PREFIX.'custom_field', 'f', 'f.custom_object_id = o.id'); - $registeredObjects = []; - $fields = $this->executeSelect($queryBuilder)->fetchAll(); + $registeredObjects = []; + $fields = $this->executeSelect($queryBuilder)->fetchAllAssociative(); + $isCustomObjectMergeFilterEnabled = $this->configProvider->isCustomObjectMergeFilterEnabled(); + $cmoType = CustomItemNameFilterQueryBuilder::getServiceId(); + $cmfType = CustomFieldFilterQueryBuilder::getServiceId(); + + if ($isCustomObjectMergeFilterEnabled) { + $cmoType = $cmfType = CustomObjectMergedFilterQueryBuilder::getServiceId(); + } foreach ($fields as $field) { $COId = $field['custom_object_id']; if (!in_array($COId, $registeredObjects, true)) { $event->addTranslation('cmo_'.$COId, [ - 'type' => CustomItemNameFilterQueryBuilder::getServiceId(), + 'type' => $cmoType, 'field' => $COId, 'foreign_table' => 'custom_objects', ]); $registeredObjects[] = $COId; } if (!$event->hasTranslation('cmf_'.$field['id']) && !empty($field['id'])) { - $event->addTranslation('cmf_'.$field['id'], $this->createTranslation($field)); + $event->addTranslation('cmf_'.$field['id'], $this->createTranslation($field, $cmfType)); } } } @@ -88,12 +87,12 @@ public function onGenerateSegmentDictionary(SegmentDictionaryGenerationEvent $ev * * @return mixed[] */ - private function createTranslation(array $fieldAttributes): array + private function createTranslation(array $fieldAttributes, string $cmfType): array { $segmentValueType = 'custom_field_value_'.$fieldAttributes['type']; return [ - 'type' => CustomFieldFilterQueryBuilder::getServiceId(), + 'type' => $cmfType, 'table' => $segmentValueType, 'field' => $fieldAttributes['id'], 'foreign_table' => 'custom_objects', diff --git a/EventListener/SegmentFiltersMergeSubscriber.php b/EventListener/SegmentFiltersMergeSubscriber.php new file mode 100644 index 000000000..133ce0f99 --- /dev/null +++ b/EventListener/SegmentFiltersMergeSubscriber.php @@ -0,0 +1,99 @@ + 'mergeCustomObjectFilters', + ]; + } + + public function mergeCustomObjectFilters(LeadListMergeFiltersEvent $event): void + { + if (!$this->configProvider->pluginIsEnabled() || (!$this->configProvider->isCustomObjectMergeFilterEnabled())) { + return; + } + + $filters = $event->getFilters(); + + $finalMergedFilters = []; + $customFieldArr = []; + $customObjectIndex = null; + foreach ($filters as $index => $filter) { + $glue = $filter['glue']; + if ('or' === strtolower($glue) && !empty($customFieldArr)) { + $finalMergedFilters = array_merge($finalMergedFilters, $this->groupCustomObject($customFieldArr)); + $customObjectIndex = null; + $customFieldArr = []; + } + + if ('custom_object' !== ($filter['object'] ?? '')) { + $finalMergedFilters[] = $filter; + continue; + } + if (!$customObjectIndex) { + $customObjectIndex = $index; + } + $key = implode('_', [$filter['object'], $filter['glue']]); + $customFieldArr[$key][$index] = $filter; + } + if (!empty($customFieldArr)) { + $finalMergedFilters = array_merge($finalMergedFilters, $this->groupCustomObject($customFieldArr)); + } + $event->setFilters($finalMergedFilters); + } + + /** + * @param array $customObjectFilters + * + * @return array + */ + private function groupCustomObject(array $customObjectFilters): array + { + $newGroupedArr = []; + foreach ($customObjectFilters as $customObjects) { + $key = key($customObjects); + $newGroupedArr[$key] = $customObjects[$key]; + $newGroupedArr[$key]['operator'] = ContactSegmentFilterFactory::CUSTOM_OPERATOR; + unset($newGroupedArr[$key]['filter']); + $mergedProperty = []; + + foreach ($customObjects as $filter) { + $mergedProperty[] = [ + 'operator' => $filter['operator'], + 'filter_value' => $filter['properties']['filter'], + 'field' => $filter['field'], + 'cmo_filter' => str_starts_with($filter['field'], 'cmo_'), + ]; + $newGroupedArr[$key]['properties'][] = $filter; + } + + unset($newGroupedArr[$key]['properties']['filter']); + $newGroupedArr[$key]['merged_property'] = $mergedProperty; + } + + return $newGroupedArr; + } +} diff --git a/EventListener/SerializerSubscriber.php b/EventListener/SerializerSubscriber.php index 9b7aa8c62..fcd3e130d 100644 --- a/EventListener/SerializerSubscriber.php +++ b/EventListener/SerializerSubscriber.php @@ -23,36 +23,12 @@ class SerializerSubscriber implements EventSubscriberInterface { - /** - * @var ConfigProvider - */ - private $configProvider; - - /** - * @var CustomItemXrefContactRepository - */ - private $customItemXrefContactRepository; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var RequestStack - */ - private $requestStack; - public function __construct( - ConfigProvider $configProvider, - CustomItemXrefContactRepository $customItemXrefContactRepository, - CustomItemModel $customItemModel, - RequestStack $requestStack + private ConfigProvider $configProvider, + private CustomItemXrefContactRepository $customItemXrefContactRepository, + private CustomItemModel $customItemModel, + private RequestStack $requestStack ) { - $this->configProvider = $configProvider; - $this->customItemXrefContactRepository = $customItemXrefContactRepository; - $this->customItemModel = $customItemModel; - $this->requestStack = $requestStack; } /** @@ -181,7 +157,7 @@ private function serializeCustomFieldValues(Collection $customFieldValues): arra try { $transformer = $customFieldValue->getCustomField()->getTypeObject()->createApiValueTransformer(); $value = $transformer->reverseTransform($customFieldValue->getValue()); - } catch (UndefinedTransformerException $e) { + } catch (UndefinedTransformerException) { $value = $customFieldValue->getValue(); } diff --git a/EventListener/TokenSubscriber.php b/EventListener/TokenSubscriber.php index d4a2e4427..f2d113ba2 100644 --- a/EventListener/TokenSubscriber.php +++ b/EventListener/TokenSubscriber.php @@ -7,10 +7,10 @@ use Mautic\CampaignBundle\Entity\Event; use Mautic\CampaignBundle\Model\EventModel; use Mautic\CoreBundle\Event\BuilderEvent; +use Mautic\CoreBundle\Event\TokenReplacementEvent; use Mautic\EmailBundle\EmailEvents; use Mautic\EmailBundle\Entity\Email; use Mautic\EmailBundle\Event\EmailSendEvent; -use Mautic\EmailBundle\EventListener\MatchFilterForLeadTrait; use Mautic\LeadBundle\Entity\LeadList; use MauticPlugin\CustomObjectsBundle\CustomItemEvents; use MauticPlugin\CustomObjectsBundle\CustomObjectEvents; @@ -25,10 +25,12 @@ use MauticPlugin\CustomObjectsBundle\Exception\InvalidCustomObjectFormatListException; use MauticPlugin\CustomObjectsBundle\Exception\InvalidSegmentFilterException; use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; +use MauticPlugin\CustomObjectsBundle\Helper\FilterEvaluator; use MauticPlugin\CustomObjectsBundle\Helper\QueryBuilderManipulatorTrait; use MauticPlugin\CustomObjectsBundle\Helper\QueryFilterHelper; use MauticPlugin\CustomObjectsBundle\Helper\TokenFormatter; use MauticPlugin\CustomObjectsBundle\Helper\TokenParser; +use MauticPlugin\CustomObjectsBundle\Model\CustomFieldModel; use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel; use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; @@ -41,74 +43,22 @@ */ class TokenSubscriber implements EventSubscriberInterface { - use MatchFilterForLeadTrait; use QueryBuilderManipulatorTrait; - /** - * @var ConfigProvider - */ - private $configProvider; - - /** - * @var QueryFilterHelper - */ - private $queryFilterHelper; - - /** - * @var QueryFilterFactory - */ - private $queryFilterFactory; - - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var TokenParser - */ - private $tokenParser; - - /** - * @var EventModel - */ - private $eventModel; - - /** - * @var EventDispatcherInterface - */ - private $eventDispatcher; - - /** - * @var TokenFormatter - */ - private $tokenFormatter; - public function __construct( - ConfigProvider $configProvider, - QueryFilterHelper $queryFilterHelper, - QueryFilterFactory $queryFilterFactory, - CustomObjectModel $customObjectModel, - CustomItemModel $customItemModel, - TokenParser $tokenParser, - EventModel $eventModel, - EventDispatcherInterface $eventDispatcher, - TokenFormatter $tokenFormatter + private ConfigProvider $configProvider, + private QueryFilterHelper $queryFilterHelper, + private QueryFilterFactory $queryFilterFactory, + private CustomObjectModel $customObjectModel, + private CustomItemModel $customItemModel, + private CustomFieldModel $customFieldModel, + private TokenParser $tokenParser, + private EventModel $eventModel, + private EventDispatcherInterface $eventDispatcher, + private TokenFormatter $tokenFormatter, + private FilterEvaluator $filterEvaluator, + private int $leadCustomItemFetchLimit ) { - $this->configProvider = $configProvider; - $this->queryFilterHelper = $queryFilterHelper; - $this->queryFilterFactory = $queryFilterFactory; - $this->customObjectModel = $customObjectModel; - $this->customItemModel = $customItemModel; - $this->tokenParser = $tokenParser; - $this->eventModel = $eventModel; - $this->eventDispatcher = $eventDispatcher; - $this->tokenFormatter = $tokenFormatter; } /** @@ -121,6 +71,7 @@ public static function getSubscribedEvents() EmailEvents::EMAIL_ON_SEND => ['decodeTokens', 0], EmailEvents::EMAIL_ON_DISPLAY => ['decodeTokens', 0], CustomItemEvents::ON_CUSTOM_ITEM_LIST_DBAL_QUERY => ['onListQuery', -1], + EmailEvents::TOKEN_REPLACEMENT => ['onTokenReplacement', 100], ]; } @@ -167,8 +118,8 @@ public function decodeTokens(EmailSendEvent $event): void $tokens->map(function (Token $token) use ($event): void { try { $customObject = $this->customObjectModel->fetchEntityByAlias($token->getCustomObjectAlias()); - $fieldValues = $this->getCustomFieldValues($customObject, $token, $event); - } catch (NotFoundException $e) { + $fieldValues = $this->getCustomFieldValues($customObject, $token, $event); + } catch (NotFoundException) { $fieldValues = null; } @@ -180,14 +131,14 @@ public function decodeTokens(EmailSendEvent $event): void $formatEvent = new CustomObjectListFormatEvent($fieldValues, $token->getFormat()); $this->eventDispatcher->dispatch( - CustomObjectEvents::ON_CUSTOM_OBJECT_LIST_FORMAT, - $formatEvent + $formatEvent, + CustomObjectEvents::ON_CUSTOM_OBJECT_LIST_FORMAT ); $result = $formatEvent->hasBeenFormatted() ? $formatEvent->getFormattedString() : $this->tokenFormatter->format($fieldValues, TokenFormatter::DEFAULT_FORMAT); - } catch (InvalidCustomObjectFormatListException $e) { + } catch (InvalidCustomObjectFormatListException) { $result = $this->tokenFormatter->format($fieldValues, TokenFormatter::DEFAULT_FORMAT); } } else { @@ -227,7 +178,7 @@ public function onListQuery(CustomItemListDbalQueryEvent $event): void } elseif ('template' && isset($source[0]) && 'campaign.event' === $source[0] && !empty($source[1])) { $campaignEventId = (int) $source[1]; - /** @var Event $campaignEvent */ + /** @var ?Event $campaignEvent */ $campaignEvent = $this->eventModel->getEntity($campaignEventId); if (!$campaignEvent) { @@ -248,7 +199,7 @@ public function onListQuery(CustomItemListDbalQueryEvent $event): void try { $queryAlias = 'filter_'.$id; $innerQueryBuilder = $this->queryFilterFactory->configureQueryBuilderFromSegmentFilter($filter, $queryAlias); - } catch (InvalidSegmentFilterException $e) { + } catch (InvalidSegmentFilterException) { continue; } @@ -312,15 +263,157 @@ private function getCustomFieldValues(CustomObject $customObject, Token $token, try { $fieldValue = $customItem->findCustomFieldValueForFieldAlias($token->getCustomFieldAlias()); // If the CO item doesn't have a value, get the default value - if ('' == $fieldValue->getValue()) { + if (empty($fieldValue->getValue())) { $fieldValue->setValue($fieldValue->getCustomField()->getDefaultValue()); } $fieldValues[] = $fieldValue->getCustomField()->getTypeObject()->valueToString($fieldValue); - } catch (NotFoundException $e) { + } catch (NotFoundException) { + // Custom field not found. + } + } + + return $fieldValues; + } + + public function onTokenReplacement(TokenReplacementEvent $event): void + { + $clickthrough = $event->getClickthrough(); + + if (!array_key_exists('dynamicContent', $clickthrough)) { + return; + } + + $lead = $event->getLead(); + $tokenData = $clickthrough['dynamicContent']; + + foreach ($tokenData as $data) { + $filterContent = $data['content']; + + $isCustomObject = false; + foreach ($data['filters'] as $filter) { + $customFieldValues = $this->getCustomFieldDataForLead($filter['filters'], (string) $lead['id']); + + if (!empty($customFieldValues)) { + $isCustomObject = true; + $lead = array_merge($lead, $customFieldValues); + } + + if ($isCustomObject && $this->filterEvaluator->evaluate($filter['filters'], $lead)) { + $filterContent = $filter['content']; + break; + } + } + + if ($isCustomObject) { + $event->addToken('{dynamiccontent="'.$data['tokenName'].'"}', $filterContent); + } + } + } + + /** + * @param array $filters + * + * @return array + */ + private function getCustomFieldDataForLead(array $filters, string $leadId): array + { + $customFieldValues = $cachedCustomItems = []; + + foreach ($filters as $condition) { + try { + if ('custom_object' !== $condition['object']) { + continue; + } + + if (str_starts_with($condition['field'], 'cmf_')) { + $customField = $this->customFieldModel->fetchEntity( + (int) explode('cmf_', $condition['field'])[1] + ); + $customObject = $customField->getCustomObject(); + $fieldAlias = $customField->getAlias(); + } elseif (str_starts_with($condition['field'], 'cmo_')) { + $customObject = $this->customObjectModel->fetchEntity( + (int) explode('cmo_', $condition['field'])[1] + ); + $fieldAlias = 'name'; + } else { + continue; + } + + $key = $customObject->getId().'-'.$leadId; + if (!isset($cachedCustomItems[$key])) { + $cachedCustomItems[$key] = $this->getCustomItems($customObject, $leadId); + } + + $result = $this->getCustomFieldValue($customObject, $fieldAlias, $cachedCustomItems[$key]); + + $customFieldValues[$condition['field']] = $result; + } catch (NotFoundException|InvalidCustomObjectFormatListException) { + continue; + } + } + + return $customFieldValues; + } + + /** + * @param array $customItems + * + * @return array + */ + private function getCustomFieldValue( + CustomObject $customObject, + string $customFieldAlias, + array $customItems + ): array { + $fieldValues = []; + + foreach ($customItems as $customItemData) { + // Name is known from the CI data array. + if ('name' === $customFieldAlias) { + $fieldValues[] = $customItemData['name']; + + continue; + } + + // Custom Field values are handled like this. + $customItem = new CustomItem($customObject); + $customItem->populateFromArray($customItemData); + $customItem = $this->customItemModel->populateCustomFields($customItem); + + try { + $fieldValue = $customItem->findCustomFieldValueForFieldAlias($customFieldAlias); + // If the CO item doesn't have a value, get the default value + if (empty($fieldValue->getValue())) { + $fieldValue->setValue($fieldValue->getCustomField()->getDefaultValue()); + } + + if (in_array($fieldValue->getCustomField()->getType(), ['multiselect', 'select'])) { + $fieldValues[] = $fieldValue->getValue(); + } else { + $fieldValues[] = $fieldValue->getCustomField()->getTypeObject()->valueToString($fieldValue); + } + } catch (NotFoundException) { // Custom field not found. } } return $fieldValues; } + + /** + * @return array + */ + private function getCustomItems(CustomObject $customObject, string $leadId): array + { + $orderBy = CustomItem::TABLE_ALIAS.'.id'; + $orderDir = 'DESC'; + + $tableConfig = new TableConfig($this->leadCustomItemFetchLimit, 1, $orderBy, $orderDir); + $tableConfig->addParameter('customObjectId', $customObject->getId()); + $tableConfig->addParameter('filterEntityType', 'contact'); + $tableConfig->addParameter('filterEntityId', $leadId); + + return $this->customItemModel->getArrayTableData($tableConfig); + } } diff --git a/Exception/ForbiddenException.php b/Exception/ForbiddenException.php index 13a5b0784..d0ddb1bd5 100644 --- a/Exception/ForbiddenException.php +++ b/Exception/ForbiddenException.php @@ -4,21 +4,14 @@ namespace MauticPlugin\CustomObjectsBundle\Exception; -use Exception; -use Throwable; - -class ForbiddenException extends Exception +class ForbiddenException extends \Exception { - /** - * @param string $entityType - * @param int $entityId - */ public function __construct( string $permission, ?string $entityType = null, ?int $entityId = null, int $code = 403, - ?Throwable $throwable = null + ?\Throwable $throwable = null ) { parent::__construct( trim("You do not have permission to {$permission} {$entityType} {$entityId}"), diff --git a/Exception/InUseException.php b/Exception/InUseException.php index 9fcda2b48..cf764e80e 100644 --- a/Exception/InUseException.php +++ b/Exception/InUseException.php @@ -4,14 +4,9 @@ namespace MauticPlugin\CustomObjectsBundle\Exception; -use Exception; - -class InUseException extends Exception +class InUseException extends \Exception { - /** - * @var array - */ - private $segmentList = []; + private array $segmentList = []; public function setSegmentList(array $segmentList): void { diff --git a/Exception/InvalidArgumentException.php b/Exception/InvalidArgumentException.php index 5252a1180..2b957473f 100644 --- a/Exception/InvalidArgumentException.php +++ b/Exception/InvalidArgumentException.php @@ -4,8 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Exception; -use Exception; - -class InvalidArgumentException extends Exception +class InvalidArgumentException extends \Exception { } diff --git a/Exception/InvalidSegmentFilterException.php b/Exception/InvalidSegmentFilterException.php index 736d3c665..595efe218 100644 --- a/Exception/InvalidSegmentFilterException.php +++ b/Exception/InvalidSegmentFilterException.php @@ -4,8 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Exception; -use Exception; - -class InvalidSegmentFilterException extends Exception +class InvalidSegmentFilterException extends \Exception { } diff --git a/Exception/InvalidValueException.php b/Exception/InvalidValueException.php index 4a3e8e856..ee91504e3 100644 --- a/Exception/InvalidValueException.php +++ b/Exception/InvalidValueException.php @@ -4,15 +4,11 @@ namespace MauticPlugin\CustomObjectsBundle\Exception; -use Exception; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; -class InvalidValueException extends Exception +class InvalidValueException extends \Exception { - /** - * @var CustomField|null - */ - private $customField; + private ?CustomField $customField = null; public function setCustomField(CustomField $customField): void { diff --git a/Exception/NoRelationshipException.php b/Exception/NoRelationshipException.php index 501cd1c17..51dc8d76f 100644 --- a/Exception/NoRelationshipException.php +++ b/Exception/NoRelationshipException.php @@ -4,14 +4,11 @@ namespace MauticPlugin\CustomObjectsBundle\Exception; -use Exception; -use Throwable; - -class NoRelationshipException extends Exception +class NoRelationshipException extends \Exception { public function __construct( int $code = 403, - ?Throwable $throwable = null + ?\Throwable $throwable = null ) { parent::__construct( 'This custom object does not have relationship fields defined.', diff --git a/Exception/NotFoundException.php b/Exception/NotFoundException.php index c99dadbb6..1961082db 100644 --- a/Exception/NotFoundException.php +++ b/Exception/NotFoundException.php @@ -4,15 +4,12 @@ namespace MauticPlugin\CustomObjectsBundle\Exception; -use Exception; -use Throwable; - -class NotFoundException extends Exception +class NotFoundException extends \Exception { public function __construct( string $message = 'Not found', int $code = 404, - ?Throwable $throwable = null + ?\Throwable $throwable = null ) { parent::__construct($message, $code, $throwable); } diff --git a/Exception/UndefinedTransformerException.php b/Exception/UndefinedTransformerException.php index 15683cac9..f93e83ec0 100644 --- a/Exception/UndefinedTransformerException.php +++ b/Exception/UndefinedTransformerException.php @@ -4,8 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Exception; -use Exception; - -class UndefinedTransformerException extends Exception +class UndefinedTransformerException extends \Exception { } diff --git a/Extension/CustomItemListeningExtension.php b/Extension/CustomItemListeningExtension.php index 04d52b972..289074ada 100644 --- a/Extension/CustomItemListeningExtension.php +++ b/Extension/CustomItemListeningExtension.php @@ -14,20 +14,8 @@ class CustomItemListeningExtension implements QueryCollectionExtensionInterface { - /** - * @var UserHelper - */ - private $userHelper; - - /** - * @var CorePermissions - */ - private $security; - - public function __construct(UserHelper $userHelper, CorePermissions $security) + public function __construct(private UserHelper $userHelper, private CorePermissions $security) { - $this->userHelper = $userHelper; - $this->security = $security; } /** @@ -38,7 +26,7 @@ public function applyToCollection( QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null - ) { + ): void { if (CustomItem::class !== $resourceClass) { return; } diff --git a/Form/DataTransformer/CustomObjectHiddenTransformer.php b/Form/DataTransformer/CustomObjectHiddenTransformer.php index 26b0d798e..b509286e7 100644 --- a/Form/DataTransformer/CustomObjectHiddenTransformer.php +++ b/Form/DataTransformer/CustomObjectHiddenTransformer.php @@ -11,14 +11,8 @@ class CustomObjectHiddenTransformer implements DataTransformerInterface { - /** - * @var CustomObjectRepository - */ - private $customObjectRepository; - - public function __construct(CustomObjectRepository $customObjectRepository) + public function __construct(private CustomObjectRepository $customObjectRepository) { - $this->customObjectRepository = $customObjectRepository; } /** diff --git a/Form/DataTransformer/OptionsToStringTransformer.php b/Form/DataTransformer/OptionsToStringTransformer.php index 3f1769ffc..db23ba498 100644 --- a/Form/DataTransformer/OptionsToStringTransformer.php +++ b/Form/DataTransformer/OptionsToStringTransformer.php @@ -15,24 +15,12 @@ class OptionsToStringTransformer implements DataTransformerInterface { /** - * @var SerializerInterface + * @var mixed[] */ - private $serializer; + private array $customFieldCache = []; - /** - * @var CustomFieldModel - */ - private $customFieldModel; - - /** - * @var CustomField[]; - */ - private $customFieldCache = []; - - public function __construct(SerializerInterface $serializer, CustomFieldModel $customFieldModel) + public function __construct(private SerializerInterface $serializer, private CustomFieldModel $customFieldModel) { - $this->serializer = $serializer; - $this->customFieldModel = $customFieldModel; } /** @@ -48,7 +36,7 @@ public function transform($options = null): string } return $this->serializer->serialize( - $options->map(function (CustomFieldOption $option) { + $options->map(function (CustomFieldOption $option): array { return $option->__toArray(); })->toArray(), 'json' diff --git a/Form/DataTransformer/ParamsToStringTransformer.php b/Form/DataTransformer/ParamsToStringTransformer.php index 48c9256fc..a90b4ebdf 100644 --- a/Form/DataTransformer/ParamsToStringTransformer.php +++ b/Form/DataTransformer/ParamsToStringTransformer.php @@ -10,14 +10,8 @@ class ParamsToStringTransformer implements DataTransformerInterface { - /** - * @var SerializerInterface - */ - private $serializer; - - public function __construct(SerializerInterface $serializer) + public function __construct(private SerializerInterface $serializer) { - $this->serializer = $serializer; } /** diff --git a/Form/Type/CampaignActionLinkType.php b/Form/Type/CampaignActionLinkType.php index 30890daf3..5021dce64 100644 --- a/Form/Type/CampaignActionLinkType.php +++ b/Form/Type/CampaignActionLinkType.php @@ -10,24 +10,14 @@ use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CampaignActionLinkType extends AbstractType { - /** - * @var CustomItemRouteProvider - */ - protected $routeProvider; - - /** - * @var TranslatorInterface - */ - protected $translator; - - public function __construct(CustomItemRouteProvider $routeProvider, TranslatorInterface $translator) - { - $this->routeProvider = $routeProvider; - $this->translator = $translator; + public function __construct( + protected CustomItemRouteProvider $routeProvider, + protected TranslatorInterface $translator + ) { } /** diff --git a/Form/Type/CampaignConditionFieldValueType.php b/Form/Type/CampaignConditionFieldValueType.php index 93f18ffb7..87da53a87 100644 --- a/Form/Type/CampaignConditionFieldValueType.php +++ b/Form/Type/CampaignConditionFieldValueType.php @@ -5,6 +5,7 @@ namespace MauticPlugin\CustomObjectsBundle\Form\Type; use MauticPlugin\CustomObjectsBundle\Model\CustomFieldModel; +use MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; @@ -12,33 +13,16 @@ use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CampaignConditionFieldValueType extends AbstractType { - /** - * @var CustomFieldModel - */ - protected $customFieldModel; - - /** - * @var CustomItemRouteProvider - */ - protected $routeProvider; - - /** - * @var TranslatorInterface - */ - protected $translator; - public function __construct( - CustomFieldModel $customFieldModel, - CustomItemRouteProvider $routeProvider, - TranslatorInterface $translator + protected CustomFieldModel $customFieldModel, + private CustomObjectModel $customObjectModel, + protected CustomItemRouteProvider $routeProvider, + protected TranslatorInterface $translator ) { - $this->customFieldModel = $customFieldModel; - $this->routeProvider = $routeProvider; - $this->translator = $translator; } /** @@ -46,10 +30,17 @@ public function __construct( */ public function buildForm(FormBuilderInterface $builder, array $options): void { - $fields = $this->customFieldModel->fetchCustomFieldsForObject($options['customObject']); - $choices = []; + $customObject = $this->customObjectModel->fetchEntity($options['customObjectId']); + $fields = $this->customFieldModel->fetchCustomFieldsForObject($customObject); + $choices = []; + foreach ($fields as $field) { - $choices[$field->getLabel()] = $field->getId(); + $choices[$field->getLabel()] = $field->getId(); + $optionAttr[$field->getLabel()] = [ + 'data-operators' => json_encode($field->getTypeObject()->getOperatorOptions()), + 'data-options' => json_encode($field->getChoices()), + 'data-field-type' => $field->getType(), + ]; } $builder->add( @@ -62,16 +53,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'attr' => [ 'class' => 'form-control', ], - 'choice_attr' => array_map( - function ($field) { - return [ - 'data-operators' => json_encode($field->getTypeObject()->getOperatorOptions()), - 'data-options' => json_encode($field->getChoices()), - 'data-field-type' => $field->getType(), - ]; - }, - $fields - ), + 'choice_attr' => $optionAttr ?? [], ] ); @@ -110,7 +92,7 @@ function ($field) { $builder->add( 'customObjectId', HiddenType::class, - ['data' => $options['customObject']->getId()] + ['data' => $options['customObjectId']] ); } @@ -119,6 +101,6 @@ function ($field) { */ public function configureOptions(OptionsResolver $resolver): void { - $resolver->setRequired(['customObject']); + $resolver->setRequired(['customObjectId']); } } diff --git a/Form/Type/CustomFieldType.php b/Form/Type/CustomFieldType.php index 3fbfd7778..765abbdf3 100644 --- a/Form/Type/CustomFieldType.php +++ b/Form/Type/CustomFieldType.php @@ -26,48 +26,15 @@ class CustomFieldType extends AbstractType { - /** - * @var CustomObjectRepository - */ - private $customObjectRepository; - - /** - * @var CustomFieldTypeProvider - */ - private $customFieldTypeProvider; - - /** - * @var ParamsToStringTransformer - */ - private $paramsToStringTransformer; - - /** - * @var OptionsToStringTransformer - */ - private $optionsToStringTransformer; - - /** - * @var CustomFieldFactory - */ - private $customFieldFactory; - - /** - * @var bool - */ - private $isCustomObjectForm; + private bool $isCustomObjectForm; public function __construct( - CustomObjectRepository $customObjectRepository, - CustomFieldTypeProvider $customFieldTypeProvider, - ParamsToStringTransformer $paramsToStringTransformer, - OptionsToStringTransformer $optionsToStringTransformer, - CustomFieldFactory $customFieldFactory + private CustomObjectRepository $customObjectRepository, + private CustomFieldTypeProvider $customFieldTypeProvider, + private ParamsToStringTransformer $paramsToStringTransformer, + private OptionsToStringTransformer $optionsToStringTransformer, + private CustomFieldFactory $customFieldFactory ) { - $this->customObjectRepository = $customObjectRepository; - $this->customFieldTypeProvider = $customFieldTypeProvider; - $this->paramsToStringTransformer = $paramsToStringTransformer; - $this->optionsToStringTransformer = $optionsToStringTransformer; - $this->customFieldFactory = $customFieldFactory; } /** @@ -128,8 +95,8 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setDefaults( [ 'data_class' => CustomField::class, - 'empty_data' => function (FormInterface $form) { - $type = $form->get('type')->getData(); + 'empty_data' => function (FormInterface $form): CustomField { + $type = $form->get('type')->getData(); $customObject = $form->get('customObject')->getData(); return $this->customFieldFactory->create($type, $customObject); @@ -199,8 +166,8 @@ private function buildModalFormFields(FormBuilderInterface $builder, array $opti $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event): void { /** @var CustomField $customField */ $customField = $event->getData(); - $form = $event->getForm(); - $hasChoices = $customField->getTypeObject()->hasChoices(); + $form = $event->getForm(); + $hasChoices = $customField->getTypeObject()->hasChoices(); $this->createDefaultValueInput($form, $customField); @@ -260,7 +227,7 @@ private function buildModalFormFields(FormBuilderInterface $builder, array $opti ] ); - $builder->setAction($options['action']); + $builder->setAction($options['action'] ?? ''); } /** @@ -270,9 +237,9 @@ private function buildModalFormFields(FormBuilderInterface $builder, array $opti private function buildPanelFormFields(FormBuilderInterface $builder): void { $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event): void { - /** @var CustomField $customField */ + /** @var ?CustomField $customField */ $customField = $event->getData(); - $form = $event->getForm(); + $form = $event->getForm(); if (!$customField) { // Custom field is new without data fetched from DB @@ -368,7 +335,7 @@ private function recreateDefaultValueBeforePost(FormBuilderInterface $builder): // Set proper type object when creating new custom field /** @var CustomField $customField */ $customField = $event->getData(); - $form = $event->getForm(); + $form = $event->getForm(); if (!$customField->getTypeObject() && $customField->getType()) { $customField->setTypeObject($this->customFieldTypeProvider->getType($customField->getType())); diff --git a/Form/Type/CustomFieldValueType.php b/Form/Type/CustomFieldValueType.php index 10051667c..fe6dab7eb 100644 --- a/Form/Type/CustomFieldValueType.php +++ b/Form/Type/CustomFieldValueType.php @@ -34,7 +34,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void try { $viewTransformer = $customField->getTypeObject()->createViewTransformer(); $formField->addViewTransformer($viewTransformer); - } catch (UndefinedTransformerException $e) { + } catch (UndefinedTransformerException) { } $builder->add($formField); diff --git a/Form/Type/CustomObjectType.php b/Form/Type/CustomObjectType.php index 2308a7f28..b5a991662 100644 --- a/Form/Type/CustomObjectType.php +++ b/Form/Type/CustomObjectType.php @@ -26,26 +26,11 @@ class CustomObjectType extends AbstractType { - /** - * @var EntityManager - */ - private $entityManager; - - /** - * @var CustomFieldTypeProvider - */ - private $customFieldTypeProvider; - - /** - * @var CustomObjectRepository - */ - private $customObjectRepository; - - public function __construct(EntityManager $entityManager, CustomFieldTypeProvider $customFieldTypeProvider, CustomObjectRepository $customObjectRepository) - { - $this->entityManager = $entityManager; - $this->customFieldTypeProvider = $customFieldTypeProvider; - $this->customObjectRepository = $customObjectRepository; + public function __construct( + private EntityManager $entityManager, + private CustomFieldTypeProvider $customFieldTypeProvider, + private CustomObjectRepository $customObjectRepository + ) { } /** @@ -205,10 +190,6 @@ function (FormEvent $event): void { $customObject = $event->getData(); $customFields = $customObject->getCustomFields(); - if (empty($customFields)) { - return; - } - /** @var CustomField $customField */ foreach ($customFields as $customField) { if (!$customField->getTypeObject()) { diff --git a/Form/Validator/Constraints/AllowUniqueIdentifierValidator.php b/Form/Validator/Constraints/AllowUniqueIdentifierValidator.php index a26d3f7b0..7d24fb6bb 100644 --- a/Form/Validator/Constraints/AllowUniqueIdentifierValidator.php +++ b/Form/Validator/Constraints/AllowUniqueIdentifierValidator.php @@ -11,11 +11,8 @@ class AllowUniqueIdentifierValidator extends ConstraintValidator { - private CustomItemModel $customItemModel; - - public function __construct(CustomItemModel $customItemModel) + public function __construct(private CustomItemModel $customItemModel) { - $this->customItemModel = $customItemModel; } /** diff --git a/Form/Validator/Constraints/CustomObjectTypeValuesValidator.php b/Form/Validator/Constraints/CustomObjectTypeValuesValidator.php index ca780b840..91aa1774d 100644 --- a/Form/Validator/Constraints/CustomObjectTypeValuesValidator.php +++ b/Form/Validator/Constraints/CustomObjectTypeValuesValidator.php @@ -13,7 +13,7 @@ class CustomObjectTypeValuesValidator extends ConstraintValidator /** * @param CustomObject $customObject */ - public function validate($customObject, Constraint $constraint) + public function validate($customObject, Constraint $constraint): void { if (CustomObject::TYPE_RELATIONSHIP === $customObject->getType()) { if (null === $customObject->getMasterObject()) { diff --git a/Helper/ContactFilterMatcher.php b/Helper/ContactFilterMatcher.php new file mode 100644 index 000000000..ccf1550a3 --- /dev/null +++ b/Helper/ContactFilterMatcher.php @@ -0,0 +1,212 @@ +getCustomFieldDataForLead($filters, $leadId); + + if (!$customFieldValues) { + return false; + } + + $hasCustomFields = true; + $lead = array_merge($lead, $customFieldValues); + + if (!isset($lead['companies']) && $this->doFiltersContainCompanyFilter($filters)) { + $lead['companies'] = $this->companyRepository->getCompaniesByLeadId($leadId); + } + + if (!isset($lead['tags']) && $this->doFiltersContainTagsFilter($filters)) { + $lead['tags'] = $this->getTagIdsByLeadId($leadId); + } + + return $this->filterEvaluator->evaluate($filters, $lead); + } + + /** + * @param mixed[] $filters + * + * @return mixed[] + */ + private function getCustomFieldDataForLead(array $filters, string $leadId): array + { + $customFieldValues = $cachedCustomItems = []; + + foreach ($filters as $condition) { + try { + if ('custom_object' !== $condition['object']) { + continue; + } + + if (str_starts_with($condition['field'], 'cmf_')) { + $customField = $this->customFieldModel->fetchEntity( + (int) explode('cmf_', $condition['field'])[1] + ); + $customObject = $customField->getCustomObject(); + $fieldAlias = $customField->getAlias(); + } elseif (str_starts_with($condition['field'], 'cmo_')) { + $customObject = $this->customObjectModel->fetchEntity( + (int) explode('cmo_', $condition['field'])[1] + ); + $fieldAlias = 'name'; + } else { + continue; + } + + $key = $customObject->getId().'-'.$leadId; + if (!isset($cachedCustomItems[$key])) { + $cachedCustomItems[$key] = $this->getCustomItems($customObject, $leadId); + } + + $result = $this->getCustomFieldValue($customObject, $fieldAlias, $cachedCustomItems[$key]); + + $customFieldValues[$condition['field']] = $result; + } catch (NotFoundException|InvalidCustomObjectFormatListException) { + continue; + } + } + + return $customFieldValues; + } + + /** + * @param mixed[] $customItems + * + * @return mixed[] + */ + private function getCustomFieldValue( + CustomObject $customObject, + string $customFieldAlias, + array $customItems + ): array { + $fieldValues = []; + + foreach ($customItems as $customItemData) { + // Name is known from the CI data array. + if ('name' === $customFieldAlias) { + $fieldValues[] = $customItemData['name']; + + continue; + } + + // Custom Field values are handled like this. + $customItem = new CustomItem($customObject); + $customItem->populateFromArray($customItemData); + $customItem = $this->customItemModel->populateCustomFields($customItem); + + try { + $fieldValue = $customItem->findCustomFieldValueForFieldAlias($customFieldAlias); + // If the CO item doesn't have a value, get the default value + if (empty($fieldValue->getValue())) { + $fieldValue->setValue($fieldValue->getCustomField()->getDefaultValue()); + } + + if (in_array($fieldValue->getCustomField()->getType(), ['multiselect', 'select'])) { + $fieldValues[] = $fieldValue->getValue(); + } else { + $fieldValues[] = $fieldValue->getCustomField()->getTypeObject()->valueToString($fieldValue); + } + } catch (NotFoundException) { + // Custom field not found. + } + } + + return $fieldValues; + } + + /** + * @return array + */ + private function getCustomItems(CustomObject $customObject, string $leadId): array + { + $orderBy = CustomItem::TABLE_ALIAS.'.id'; + $orderDir = 'DESC'; + + $tableConfig = new TableConfig($this->leadCustomItemFetchLimit, 1, $orderBy, $orderDir); + $tableConfig->addParameter('customObjectId', $customObject->getId()); + $tableConfig->addParameter('filterEntityType', 'contact'); + $tableConfig->addParameter('filterEntityId', $leadId); + + return $this->customItemModel->getArrayTableData($tableConfig); + } + + /** + * @param mixed[] $filters + */ + private function doFiltersContainCompanyFilter(array $filters): bool + { + foreach ($filters as $filter) { + $object = $filter['object'] ?? ''; + + if ('company' === $object) { + return true; + } + + if (str_starts_with($filter['field'], 'company') && 'company' !== $filter['field']) { + return true; + } + } + + return false; + } + + /** + * @param mixed[] $filters + */ + private function doFiltersContainTagsFilter(array $filters): bool + { + foreach ($filters as $filter) { + if ('tags' === ($filter['type'] ?? null)) { + return true; + } + } + + return false; + } + + /** + * @return string[] + */ + public function getTagIdsByLeadId(string $leadId): array + { + return $this->connection->createQueryBuilder() + ->select('tag_id') + ->from(MAUTIC_TABLE_PREFIX.'lead_tags_xref', 'x') + ->where('x.lead_id = :leadId') + ->setParameter('leadId', $leadId) + ->executeQuery() + ->fetchFirstColumn(); + } +} diff --git a/Helper/FilterEvaluator.php b/Helper/FilterEvaluator.php new file mode 100644 index 000000000..e2e7d09a3 --- /dev/null +++ b/Helper/FilterEvaluator.php @@ -0,0 +1,191 @@ + + */ +class FilterEvaluator +{ + /** + * @param array $filters + * @param LeadArray $lead + * + * @throws OperatorsNotFoundException + */ + public function evaluate(array $filters, array $lead): bool + { + if (empty($lead['id'])) { + return false; + } + + /** @var array $groups */ + $groups = []; + $groupNum = 0; + + foreach ($filters as $data) { + if (!array_key_exists($data['field'], $lead)) { + continue; + } + + if (0 === $groupNum || 'or' === $data['glue']) { + ++$groupNum; + $groups[$groupNum] = null; + } + + if (false === $groups[$groupNum]) { + continue; + } + + if (null === $groups[$groupNum]) { + $groups[$groupNum] = false; + } + + $isCustomObject = 'custom_object' === $data['object']; + $leadValues = $isCustomObject ? $lead[$data['field']] : [$lead[$data['field']]]; + $filterVal = $data['filter']; + + if (!is_array($leadValues)) { + $leadValues = [$leadValues]; + } + + // No linked custom items: only 'empty' operator can match. + if ($isCustomObject && [] === $leadValues) { + $groups[$groupNum] = 'empty' === $data['operator']; + continue; + } + + $matched = false; + foreach ($leadValues as $leadVal) { + [$leadVal, $filterVal] = $this->coerceTypes($data['type'], $leadVal, $filterVal); + if ($this->applyOperator($data['operator'], $data['type'], $leadVal, $filterVal)) { + $matched = true; + break; + } + } + + $groups[$groupNum] = $matched; + } + + return in_array(true, $groups, true); + } + + /** + * @return array{mixed, mixed} + */ + private function coerceTypes(string $type, mixed $leadVal, mixed $filterVal): array + { + switch ($type) { + case 'boolean': + if (null !== $leadVal) { + $leadVal = (bool) $leadVal; + } + if (null !== $filterVal) { + $filterVal = (bool) $filterVal; + } + break; + case 'datetime': + case 'time': + if (null !== $leadVal && null !== $filterVal) { + if (2 === substr_count($leadVal, ':') && 1 === substr_count($filterVal, ':')) { + $filterVal .= ':00'; + } + } + break; + case 'tags': + case 'select': + case 'multiselect': + if (!is_array($leadVal) && !empty($leadVal)) { + $leadVal = explode('|', $leadVal); + } + if (null !== $filterVal && !is_array($filterVal)) { + $filterVal = explode('|', $filterVal); + } + break; + case 'int': + case 'number': + $leadVal = (int) $leadVal; + $filterVal = (int) $filterVal; + break; + } + + return [$leadVal, $filterVal]; + } + + /** + * @throws OperatorsNotFoundException + */ + private function applyOperator(string $operator, string $type, mixed $leadVal, mixed $filterVal): bool + { + switch ($operator) { + case '=': + return 'boolean' === $type ? $leadVal === $filterVal : $leadVal == $filterVal; + case '!=': + return 'boolean' === $type ? $leadVal !== $filterVal : $leadVal != $filterVal; + case 'gt': + return $leadVal > $filterVal; + case 'gte': + return $leadVal >= $filterVal; + case 'lt': + return $leadVal < $filterVal; + case 'lte': + return $leadVal <= $filterVal; + case 'empty': + return empty($leadVal); + case '!empty': + return !empty($leadVal); + case 'like': + $pattern = str_replace(['.', '*', '%'], ['\.', '\*', '.*'], $filterVal); + + return 1 === preg_match('/'.$pattern.'/', $leadVal); + case '!like': + $pattern = str_replace(['.', '*', '%'], ['\.', '\*', '.*'], $filterVal); + + return 1 !== preg_match('/'.$pattern.'/', $leadVal); + case OperatorOptions::IN: + return $this->checkLeadValueIsInFilter($leadVal, $filterVal, false); + case OperatorOptions::NOT_IN: + return $this->checkLeadValueIsInFilter($leadVal, $filterVal, true); + case 'regexp': + return 1 === preg_match('/'.$filterVal.'/i', $leadVal); + case '!regexp': + return 1 !== preg_match('/'.$filterVal.'/i', $leadVal); + case 'startsWith': + return str_starts_with($leadVal, $filterVal); + case 'endsWith': + return 0 === strcmp(substr($leadVal, strlen($leadVal) - strlen($filterVal)), $filterVal); + case 'contains': + return str_contains((string) $leadVal, (string) $filterVal); + default: + throw new OperatorsNotFoundException('Operator is not defined or invalid operator found.'); + } + } + + private function checkLeadValueIsInFilter(mixed $leadVal, mixed $filterVal, bool $defaultFlag): bool + { + $leadVal = !is_array($leadVal) ? [$leadVal] : $leadVal; + $filterVal = !is_array($filterVal) ? [$filterVal] : $filterVal; + $retFlag = $defaultFlag; + + foreach ($leadVal as $v) { + if (in_array($v, $filterVal)) { + $retFlag = !$defaultFlag; + break; + } + } + + return $retFlag; + } +} diff --git a/Helper/LockFlashMessageHelper.php b/Helper/LockFlashMessageHelper.php index 6962791ff..322f34dad 100644 --- a/Helper/LockFlashMessageHelper.php +++ b/Helper/LockFlashMessageHelper.php @@ -7,40 +7,16 @@ use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Service\FlashBag; use Symfony\Component\Routing\Router; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class LockFlashMessageHelper { - /** - * @var CoreParametersHelper - */ - private $coreParametersHelper; - - /** - * @var TranslatorInterface - */ - private $translator; - - /** - * @var FlashBag - */ - private $flashBag; - - /** - * @var Router - */ - private $router; - public function __construct( - CoreParametersHelper $coreParametersHelper, - TranslatorInterface $translator, - FlashBag $flashBag, - Router $router + private CoreParametersHelper $coreParametersHelper, + private TranslatorInterface $translator, + private FlashBag $flashBag, + private Router $router ) { - $this->coreParametersHelper = $coreParametersHelper; - $this->translator = $translator; - $this->flashBag = $flashBag; - $this->router = $router; } /** diff --git a/Helper/QueryBuilderManipulatorTrait.php b/Helper/QueryBuilderManipulatorTrait.php index 0b7d6f386..eba753f15 100644 --- a/Helper/QueryBuilderManipulatorTrait.php +++ b/Helper/QueryBuilderManipulatorTrait.php @@ -4,6 +4,8 @@ namespace MauticPlugin\CustomObjectsBundle\Helper; +use Doctrine\DBAL\ArrayParameterType; +use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Query\QueryBuilder; use MauticPlugin\CustomObjectsBundle\Segment\Query\UnionQueryContainer; @@ -18,7 +20,7 @@ trait QueryBuilderManipulatorTrait private function copyParams($fromQueryBuilder, QueryBuilder $toQueryBuilder): void { foreach ($fromQueryBuilder->getParameters() as $key => $value) { - $paramType = is_array($value) ? $toQueryBuilder->getConnection()::PARAM_STR_ARRAY : null; + $paramType = is_array($value) ? ArrayParameterType::STRING : ParameterType::STRING; $toQueryBuilder->setParameter($key, $value, $paramType); } } diff --git a/Helper/QueryFilterFactory.php b/Helper/QueryFilterFactory.php index b8290adb5..89f4a20fc 100644 --- a/Helper/QueryFilterFactory.php +++ b/Helper/QueryFilterFactory.php @@ -14,48 +14,15 @@ class QueryFilterFactory { - /** - * @var EntityManager - */ - private $entityManager; - - /** - * @var CustomFieldTypeProvider - */ - private $fieldTypeProvider; - - /** - * @var UnionQueryContainer|null - */ - private $unionQueryContainer; - - /** - * @var CustomFieldRepository - */ - private $customFieldRepository; - - /** - * @var Calculator - */ - private $calculator; - - /** - * @var int - */ - private $itemRelationLevelLimit; + private ?UnionQueryContainer $unionQueryContainer = null; public function __construct( - EntityManager $entityManager, - CustomFieldTypeProvider $fieldTypeProvider, - CustomFieldRepository $customFieldRepository, - Calculator $calculator, - int $itemRelationLevelLimit + private EntityManager $entityManager, + private CustomFieldTypeProvider $fieldTypeProvider, + private CustomFieldRepository $customFieldRepository, + private Calculator $calculator, + private int $itemRelationLevelLimit ) { - $this->entityManager = $entityManager; - $this->fieldTypeProvider = $fieldTypeProvider; - $this->customFieldRepository = $customFieldRepository; - $this->calculator = $calculator; - $this->itemRelationLevelLimit = $itemRelationLevelLimit; } public function createQuery( @@ -164,4 +131,14 @@ private function createMultilevelQueries(string $alias, int $segmentFilterFieldI $this->unionQueryContainer->add($qb); } } + + public function getCustomFieldTypeById(int $segmentFilterFieldId): string + { + return $this->customFieldRepository->getCustomFieldTypeById($segmentFilterFieldId); + } + + public function getTableNameFromType(string $segmentFilterFieldType): string + { + return $this->fieldTypeProvider->getType($segmentFilterFieldType)->getTableName(); + } } diff --git a/Helper/QueryFilterFactory/Calculator.php b/Helper/QueryFilterFactory/Calculator.php index a634bef2a..c79575693 100644 --- a/Helper/QueryFilterFactory/Calculator.php +++ b/Helper/QueryFilterFactory/Calculator.php @@ -12,29 +12,19 @@ class Calculator private const COLUMN_SUFFIX_LOWER = 'lower'; private const COLUMN_SUFFIX_HIGHER = 'higher'; - /** - * @var int - */ - private $level; + private ?int $level = null; /** * Matrix ciphers - joins per query. - * - * @var int */ - private $cipherCount; + private ?int $cipherCount = null; /** * Number of union queries to be generated. - * - * @var int */ - private $totalQueryCountPerLevel; + private float|int|null $totalQueryCountPerLevel = null; - /** - * @var string - */ - private $matrix; + private ?string $matrix = null; /** * Reset counter with new level. diff --git a/Helper/QueryFilterHelper.php b/Helper/QueryFilterHelper.php index 171901f06..d5ba3d24c 100644 --- a/Helper/QueryFilterHelper.php +++ b/Helper/QueryFilterHelper.php @@ -4,13 +4,13 @@ namespace MauticPlugin\CustomObjectsBundle\Helper; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\ArrayParameterType; +use Doctrine\DBAL\Query\Expression\CompositeExpression; use Doctrine\ORM\EntityManager; use Mautic\LeadBundle\Segment\ContactSegmentFilter; -use Mautic\LeadBundle\Segment\Query\Expression\CompositeExpression; use Mautic\LeadBundle\Segment\Query\QueryBuilder as SegmentQueryBuilder; +use Mautic\LeadBundle\Segment\RandomParameterName; use MauticPlugin\CustomObjectsBundle\Exception\InvalidArgumentException; -use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider; use MauticPlugin\CustomObjectsBundle\Repository\DbalQueryTrait; use MauticPlugin\CustomObjectsBundle\Segment\Query\UnionQueryContainer; @@ -18,40 +18,20 @@ class QueryFilterHelper { use DbalQueryTrait; - /** - * @var EntityManager - */ - private $entityManager; - - /** - * @var QueryFilterFactory - */ - private $queryFilterFactory; - - /** - * @var CustomFieldTypeProvider - */ - private $fieldTypeProvider; - - /** - * @var int - */ - private $itemRelationLevelLimit; - public function __construct( - EntityManager $entityManager, - QueryFilterFactory $queryFilterFactory + private EntityManager $entityManager, + private QueryFilterFactory $queryFilterFactory, + private RandomParameterName $randomParameterNameService ) { - $this->entityManager = $entityManager; - $this->queryFilterFactory = $queryFilterFactory; } public function createValueQuery( string $alias, - ContactSegmentFilter $segmentFilter + ContactSegmentFilter $segmentFilter, + bool $filterAlreadyNegated = false ): UnionQueryContainer { $unionQueryContainer = $this->queryFilterFactory->createQuery($alias, $segmentFilter); - $this->addCustomFieldValueExpressionFromSegmentFilter($unionQueryContainer, $alias, $segmentFilter); + $this->addCustomFieldValueExpressionFromSegmentFilter($unionQueryContainer, $alias, $segmentFilter, $filterAlreadyNegated); return $unionQueryContainer; } @@ -88,17 +68,27 @@ public function addContactIdRestriction(SegmentQueryBuilder $queryBuilder, strin public function addCustomFieldValueExpressionFromSegmentFilter( UnionQueryContainer $unionQueryContainer, string $tableAlias, - ContactSegmentFilter $filter + ContactSegmentFilter $filter, + bool $filterAlreadyNegated = false ): void { + $filterValue = $filter->getParameterValue(); foreach ($unionQueryContainer as $segmentQueryBuilder) { - $expression = $this->getCustomValueValueExpression($segmentQueryBuilder, $tableAlias, $filter->getOperator()); + $valueParameter = $this->randomParameterNameService->generateRandomParameterName(); + $expression = $this->getCustomValueValueExpression( + $segmentQueryBuilder, + $tableAlias, + $filter, + $valueParameter, + $filterAlreadyNegated, + $filterValue + ); $this->addOperatorExpression( $segmentQueryBuilder, - $tableAlias, $expression, $filter->getOperator(), - $filter->getParameterValue() + $filterValue, + $valueParameter ); } } @@ -109,8 +99,9 @@ public function addCustomObjectNameExpression( string $operator, ?string $value ): void { - $expression = $this->getCustomObjectNameExpression($queryBuilder, $tableAlias, $operator); - $this->addOperatorExpression($queryBuilder, $tableAlias, $expression, $operator, $value); + $valueParameter = $this->randomParameterNameService->generateRandomParameterName(); + $expression = $this->getCustomObjectNameExpression($queryBuilder, $tableAlias, $operator, $valueParameter); + $this->addOperatorExpression($queryBuilder, $expression, $operator, $value, $valueParameter); } /** @@ -119,10 +110,10 @@ public function addCustomObjectNameExpression( */ private function addOperatorExpression( SegmentQueryBuilder $segmentQueryBuilder, - string $tableAlias, $expression, string $operator, - $value + $value, + string $valueParameter ): void { $valueType = null; @@ -134,12 +125,11 @@ private function addOperatorExpression( case 'notIn': case 'multiselect': case 'in': - $valueType = Connection::PARAM_STR_ARRAY; - $valueParameter = $tableAlias.'_value_value'; - + $valueType = ArrayParameterType::STRING; + $segmentQueryBuilder->setParameter($valueParameter, $value, $valueType); break; default: - $valueParameter = $tableAlias.'_value_value'; + $segmentQueryBuilder->setParameter($valueParameter, $value, $valueType); } switch ($operator) { @@ -147,76 +137,108 @@ private function addOperatorExpression( break; default: $segmentQueryBuilder->andWhere($expression); - break; } - - if (isset($valueParameter)) { - $segmentQueryBuilder->setParameter($valueParameter, $value, $valueType); - } } /** * Form the logical expression needed to limit the CustomValue's value for given operator. * + * @param mixed $filterParameterValue + * * @return CompositeExpression|string */ - private function getCustomValueValueExpression(SegmentQueryBuilder $customQuery, string $tableAlias, string $operator) - { + private function getCustomValueValueExpression( + SegmentQueryBuilder $customQuery, + string $tableAlias, + ContactSegmentFilter $filter, + string $valueParameter, + bool $alreadyNegated = false, + $filterParameterValue = null + ) { + $operator = $filter->getOperator(); + if ($alreadyNegated) { + switch ($operator) { + case 'empty': + $operator = 'notEmpty'; + break; + case 'neq': + $operator = 'eq'; + break; + case '!between': + case 'notBetween': + $operator = 'between'; + break; + } + } + switch ($operator) { case 'empty': $expression = $customQuery->expr()->orX( $customQuery->expr()->isNull($tableAlias.'_value.value'), - $customQuery->expr()->eq($tableAlias.'_value.value', $customQuery->expr()->literal('')) ); - + if ($filter->doesColumnSupportEmptyValue()) { + $expression->add( + $customQuery->expr()->eq($tableAlias.'_value.value', $customQuery->expr()->literal('')) + ); + } break; case 'notEmpty': - $expression = $customQuery->expr()->andX( + $expression = $customQuery->expr()->and( $customQuery->expr()->isNotNull($tableAlias.'_value.value'), - $customQuery->expr()->neq($tableAlias.'_value.value', $customQuery->expr()->literal('')) ); + if ($filter->doesColumnSupportEmptyValue()) { + $expression->add( + $customQuery->expr()->neq($tableAlias.'_value.value', $customQuery->expr()->literal('')) + ); + } break; case 'notIn': case '!multiselect': case 'in': case 'multiselect': - $valueParameter = $tableAlias.'_value_value'; $expression = $customQuery->expr()->in( $tableAlias.'_value.value', - ":${valueParameter}" + ":{$valueParameter}" ); break; case 'neq': - $valueParameter = $tableAlias.'_value_value'; - $expression = $customQuery->expr()->orX( - $customQuery->expr()->neq($tableAlias.'_value.value', ":${valueParameter}"), + $expression = $customQuery->expr()->or( + $customQuery->expr()->neq($tableAlias.'_value.value', ":{$valueParameter}"), $customQuery->expr()->isNull($tableAlias.'_value.value') ); break; case 'contains': - $valueParameter = $tableAlias.'_value_value'; - $expression = $customQuery->expr()->like($tableAlias.'_value.value', "%:{$valueParameter}%"); break; case 'notLike': - $valueParameter = $tableAlias.'_value_value'; - - $expression = $customQuery->expr()->orX( + $expression = $customQuery->expr()->or( $customQuery->expr()->isNull($tableAlias.'_value.value'), - $customQuery->expr()->like($tableAlias.'_value.value', ":${valueParameter}") + $customQuery->expr()->like($tableAlias.'_value.value', ":{$valueParameter}") ); break; + case 'between': + case 'notBetween': + if (is_array($filterParameterValue)) { + $expression = $customQuery->expr()->{$operator}( + $tableAlias.'_value.value', + array_map(function (mixed $val) use ($customQuery): mixed { + return is_numeric($val) && intval($val) === $val ? + $val : $customQuery->expr()->literal($val); + }, array_values($filterParameterValue)) + ); + break; + } + // no break default: - $valueParameter = $tableAlias.'_value_value'; $expression = $customQuery->expr()->{$operator}( $tableAlias.'_value.value', - ":${valueParameter}" + ":{$valueParameter}" ); } @@ -228,58 +250,38 @@ private function getCustomValueValueExpression(SegmentQueryBuilder $customQuery, * * @return CompositeExpression|string */ - private function getCustomObjectNameExpression(SegmentQueryBuilder $customQuery, string $tableAlias, string $operator) - { - switch ($operator) { - case 'empty': - $expression = $customQuery->expr()->orX( - $customQuery->expr()->isNull($tableAlias.'_item.name'), - $customQuery->expr()->eq($tableAlias.'_item.name', $customQuery->expr()->literal('')) - ); - - break; - case 'notEmpty': - $expression = $customQuery->expr()->andX( - $customQuery->expr()->isNotNull($tableAlias.'_item.name'), - $customQuery->expr()->neq($tableAlias.'_item.name', $customQuery->expr()->literal('')) - ); - - break; - case 'notIn': - case 'in': - $valueParameter = $tableAlias.'_value_value'; - $expression = $customQuery->expr()->in( - $tableAlias.'_item.name', - ":${valueParameter}" - ); - - break; - case 'neq': - $valueParameter = $tableAlias.'_value_value'; - $expression = $customQuery->expr()->orX( - $customQuery->expr()->eq($tableAlias.'_item.name', ":${valueParameter}"), - $customQuery->expr()->isNull($tableAlias.'_item.name') - ); - - break; - case 'notLike': - $valueParameter = $tableAlias.'_value_value'; - - $expression = $customQuery->expr()->orX( - $customQuery->expr()->isNull($tableAlias.'_item.name'), - $customQuery->expr()->like($tableAlias.'_item.name', ":${valueParameter}") - ); - - break; - default: - $valueParameter = $tableAlias.'_value_value'; - $expression = $customQuery->expr()->{$operator}( - $tableAlias.'_item.name', - ":${valueParameter}" - ); - } - - return $expression; + private function getCustomObjectNameExpression( + SegmentQueryBuilder $customQuery, + string $tableAlias, + string $operator, + string $valueParameter + ) { + return match ($operator) { + 'empty' => $customQuery->expr()->or( + $customQuery->expr()->isNull($tableAlias.'_item.name'), + $customQuery->expr()->eq($tableAlias.'_item.name', $customQuery->expr()->literal('')) + ), + 'notEmpty' => $customQuery->expr()->and( + $customQuery->expr()->isNotNull($tableAlias.'_item.name'), + $customQuery->expr()->neq($tableAlias.'_item.name', $customQuery->expr()->literal('')) + ), + 'notIn', 'in' => $customQuery->expr()->in( + $tableAlias.'_item.name', + ":{$valueParameter}" + ), + 'neq' => $customQuery->expr()->orX( + $customQuery->expr()->eq($tableAlias.'_item.name', ':'.$valueParameter), + $customQuery->expr()->isNull($tableAlias.'_item.name') + ), + 'notLike' => $customQuery->expr()->or( + $customQuery->expr()->isNull($tableAlias.'_item.name'), + $customQuery->expr()->like($tableAlias.'_item.name', ":{$valueParameter}") + ), + default => $customQuery->expr()->{$operator}( + $tableAlias.'_item.name', + ":{$valueParameter}" + ), + }; } /** @@ -313,4 +315,130 @@ private function getBasicItemQueryBuilder(SegmentQueryBuilder $queryBuilder, str return $customFieldQueryBuilder; } + + public function createMergeFilterQuery( + ContactSegmentFilter $segmentFilter, + string $leadsTableAlias + ): SegmentQueryBuilder { + $customItemXrefContactAlias = 'cix'; + $qb = new SegmentQueryBuilder($this->entityManager->getConnection()); + $qb->select('1') + ->from(MAUTIC_TABLE_PREFIX.'custom_item_xref_contact', $customItemXrefContactAlias) + ->where($qb->expr()->eq($customItemXrefContactAlias.'.contact_id', $leadsTableAlias.'.id')); + + $joinedAlias = []; + + foreach ($segmentFilter->contactSegmentFilterCrate->getMergedProperty() as $filter) { + $segmentFilterFieldId = (int) $filter['field']; + $segmentFilterFieldType = $filter['type'] ?: $this->queryFilterFactory + ->getCustomFieldTypeById($segmentFilterFieldId); + $dataTable = $this->queryFilterFactory->getTableNameFromType($segmentFilterFieldType); + $segmentMergedFilter = $segmentFilter; + $segmentFilterFieldOperator = (string) $filter['operator']; + + $alias = $customItemXrefContactAlias.'_'.$segmentFilterFieldId.'_'.$filter['type']; + $aliasValue = $alias.'_value'; + $isCmoFilter = $filter['cmo_filter'] ?? false; + $cinAlias = 'cin_'.$segmentFilterFieldId; + $cinAliasItem = $cinAlias.'_item'; + $valueParameter = $this->randomParameterNameService->generateRandomParameterName(); + + if ($isCmoFilter && !in_array($cinAliasItem, $joinedAlias, true)) { + $this->joinMergeCustomItem($qb, $customItemXrefContactAlias, $cinAliasItem, $segmentFilterFieldId); + $joinedAlias[] = $cinAliasItem; + } elseif (!in_array($aliasValue, $joinedAlias, true)) { + $this->joinMergeCustomField( + $qb, + $customItemXrefContactAlias, + $dataTable, + $aliasValue, + $segmentFilterFieldId + ); + $joinedAlias[] = $aliasValue; + } + + $this->addOperatorExpression( + $qb, + $this->getMergeExpression( + $isCmoFilter, + $qb, + $cinAlias, + $alias, + $segmentMergedFilter, + $valueParameter + ), + $segmentFilterFieldOperator, + $filter['filter_value'], + $valueParameter + ); + } + + return $qb; + } + + private function joinMergeCustomItem( + SegmentQueryBuilder $qb, + string $customItemXrefContactAlias, + string $cinAliasItem, + int $segmentFilterFieldId + ): void { + $qb->leftJoin( + $customItemXrefContactAlias, + MAUTIC_TABLE_PREFIX.'custom_item', + $cinAliasItem, + "$customItemXrefContactAlias.custom_item_id = $cinAliasItem.id" + ); + $qb->andWhere($qb->expr()->eq($cinAliasItem.'.custom_object_id', $segmentFilterFieldId)); + } + + private function joinMergeCustomField( + SegmentQueryBuilder $qb, + string $customItemXrefContactAlias, + string $dataTable, + string $aliasValue, + int $segmentFilterFieldId + ): void { + $qb->innerJoin( + $customItemXrefContactAlias, + MAUTIC_TABLE_PREFIX.$dataTable, + $aliasValue, + "$aliasValue.custom_item_id = $customItemXrefContactAlias.custom_item_id AND " + ."$aliasValue.custom_field_id = $segmentFilterFieldId" + ); + } + + /** + * @phpstan-ignore-next-line + * + * @return CompositeExpression|string + */ + private function getMergeExpression( + bool $isCmoFilter, + SegmentQueryBuilder $qb, + string $cinAlias, + string $alias, + ContactSegmentFilter $filter, + string $valueParameter + ) { + $segmentFilterFieldOperator = $filter->getOperator(); + if ($isCmoFilter) { + $expression = $this->getCustomObjectNameExpression( + $qb, + $cinAlias, + $segmentFilterFieldOperator, + $valueParameter + ); + } else { + $expression = $this->getCustomValueValueExpression( + $qb, + $alias, + $filter, + $valueParameter, + false, + $filter->getParameterValue() + ); + } + + return $expression; + } } diff --git a/Helper/TokenFormatter.php b/Helper/TokenFormatter.php index af5379670..62bd37eee 100644 --- a/Helper/TokenFormatter.php +++ b/Helper/TokenFormatter.php @@ -117,16 +117,15 @@ private function htmlList(array $values, string $tag): string foreach ($values as $item) { $list .= '
  • '.$item.'
  • '; } - $list .= ""; - return $list; + return $list.""; } private function removeEmptyValues(array $values): array { return array_filter( $values, - function ($value) { + function ($value): bool { return '' !== trim($value); } ); diff --git a/Helper/TokenParser.php b/Helper/TokenParser.php index c7e4d845b..f97d67f9c 100644 --- a/Helper/TokenParser.php +++ b/Helper/TokenParser.php @@ -27,7 +27,7 @@ public function findTokens(string $content): ArrayCollection try { $this->extractAliases($parts[0], $token); - } catch (\LengthException $e) { + } catch (\LengthException) { // Invalid token, pretend like we did not see it. continue; } @@ -109,7 +109,7 @@ private function getPartsDividedByPipe(string $tokenDataRaw): array private function trimArrayElements(array $array): array { return array_map( - function ($part) { + function ($part): string { return trim($part); }, $array diff --git a/Migrations/Version_0_0_1.php b/Migrations/Version_0_0_1.php index 5b0310033..6a25021ae 100644 --- a/Migrations/Version_0_0_1.php +++ b/Migrations/Version_0_0_1.php @@ -10,10 +10,7 @@ class Version_0_0_1 extends AbstractMigration { - /** - * @var string - */ - private $table = 'custom_object'; + private string $table = 'custom_object'; /** * {@inheritdoc} @@ -22,7 +19,7 @@ protected function isApplicable(Schema $schema): bool { try { return !$schema->getTable($this->concatPrefix($this->table))->hasColumn('description'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_11.php b/Migrations/Version_0_0_11.php index caaaaf385..078e95a01 100644 --- a/Migrations/Version_0_0_11.php +++ b/Migrations/Version_0_0_11.php @@ -5,16 +5,13 @@ namespace MauticPlugin\CustomObjectsBundle\Migrations; use Doctrine\DBAL\Schema\Schema; -use Mautic\CoreBundle\Exception\SchemaException; +use Doctrine\DBAL\Schema\SchemaException; use Mautic\IntegrationsBundle\Migration\AbstractMigration; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; class Version_0_0_11 extends AbstractMigration { - /** - * @var string - */ - private $table = 'custom_object'; + private string $table = 'custom_object'; /** * {@inheritdoc} @@ -24,9 +21,9 @@ protected function isApplicable(Schema $schema): bool $tableCustomObject = $this->concatPrefix($this->table); try { - return !$schema->getTable($tableCustomObject)->hasColumn('type') || - !$schema->getTable($tableCustomObject)->hasColumn('master_object'); - } catch (SchemaException $e) { + return !$schema->getTable($tableCustomObject)->hasColumn('type') + || !$schema->getTable($tableCustomObject)->hasColumn('master_object'); + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_13.php b/Migrations/Version_0_0_13.php index 5766ef58e..adcbf34e6 100644 --- a/Migrations/Version_0_0_13.php +++ b/Migrations/Version_0_0_13.php @@ -17,7 +17,7 @@ protected function isApplicable(Schema $schema): bool { try { return !$schema->getTable($this->concatPrefix('custom_object'))->hasColumn('relationship_object'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_14.php b/Migrations/Version_0_0_14.php index 918a3c1f6..4df17e9f2 100644 --- a/Migrations/Version_0_0_14.php +++ b/Migrations/Version_0_0_14.php @@ -17,7 +17,7 @@ protected function isApplicable(Schema $schema): bool { try { return !$schema->getTable($this->concatPrefix('custom_field'))->hasColumn('show_in_custom_object_detail_list'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_15.php b/Migrations/Version_0_0_15.php index 4514feb44..da930ccf1 100644 --- a/Migrations/Version_0_0_15.php +++ b/Migrations/Version_0_0_15.php @@ -14,7 +14,7 @@ protected function isApplicable(Schema $schema): bool { try { return $schema->getTable($this->concatPrefix('custom_object'))->hasColumn('relationship'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_16.php b/Migrations/Version_0_0_16.php index 17af16cf6..e9279848c 100644 --- a/Migrations/Version_0_0_16.php +++ b/Migrations/Version_0_0_16.php @@ -5,7 +5,7 @@ namespace MauticPlugin\CustomObjectsBundle\Migrations; use Doctrine\DBAL\Schema\Schema; -use Mautic\CoreBundle\Exception\SchemaException; +use Doctrine\DBAL\Schema\SchemaException; use Mautic\IntegrationsBundle\Migration\AbstractMigration; class Version_0_0_16 extends AbstractMigration @@ -16,9 +16,9 @@ protected function isApplicable(Schema $schema): bool $table = $schema->getTable($tableName); try { - return $table->hasColumn('required') && - null === $table->getColumn('required')->getDefault(); - } catch (SchemaException $e) { + return $table->hasColumn('required') + && null === $table->getColumn('required')->getDefault(); + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_17.php b/Migrations/Version_0_0_17.php index 531ea816d..e21757262 100644 --- a/Migrations/Version_0_0_17.php +++ b/Migrations/Version_0_0_17.php @@ -10,15 +10,14 @@ class Version_0_0_17 extends AbstractMigration { - /** @var Schema */ - private $schema; + private ?Schema $schema = null; protected function isApplicable(Schema $schema): bool { $this->schema = $schema; try { return !$this->schema->getTable($this->concatPrefix('custom_object'))->hasForeignKey('FK_CO_RELATIONSHIP_OBJECT'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_18.php b/Migrations/Version_0_0_18.php index 1c389680c..453eb5223 100644 --- a/Migrations/Version_0_0_18.php +++ b/Migrations/Version_0_0_18.php @@ -10,15 +10,14 @@ class Version_0_0_18 extends AbstractMigration { - /** @var Schema */ - private $schema; + private ?Schema $schema = null; protected function isApplicable(Schema $schema): bool { $this->schema = $schema; try { return !$this->schema->getTable($this->concatPrefix('custom_object'))->hasForeignKey('FK_CO_MASTER_OBJECT'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_19.php b/Migrations/Version_0_0_19.php index a76f762da..c91718737 100644 --- a/Migrations/Version_0_0_19.php +++ b/Migrations/Version_0_0_19.php @@ -13,8 +13,7 @@ class Version_0_0_19 extends AbstractMigration { public const FOREIGN_KEY_TO_DELETE = '/^FK_\d+594D0CC2$/'; - /** @var Schema */ - private $schema; + private ?Schema $schema = null; protected function isApplicable(Schema $schema): bool { diff --git a/Migrations/Version_0_0_2.php b/Migrations/Version_0_0_2.php index 0bcd7419b..a8d7169a5 100644 --- a/Migrations/Version_0_0_2.php +++ b/Migrations/Version_0_0_2.php @@ -9,10 +9,7 @@ class Version_0_0_2 extends AbstractMigration { - /** - * @var string - */ - private $table = 'custom_item_xref_custom_item'; + private string $table = 'custom_item_xref_custom_item'; /** * {@inheritdoc} diff --git a/Migrations/Version_0_0_21.php b/Migrations/Version_0_0_21.php index 6a7ca6b7f..e1316fe40 100644 --- a/Migrations/Version_0_0_21.php +++ b/Migrations/Version_0_0_21.php @@ -18,7 +18,7 @@ protected function isApplicable(Schema $schema): bool try { return !$schema->getTable($tableCustomObject)->hasColumn('is_unique_identifier'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_27.php b/Migrations/Version_0_0_27.php index d9feb6cc2..d153caa85 100644 --- a/Migrations/Version_0_0_27.php +++ b/Migrations/Version_0_0_27.php @@ -18,7 +18,7 @@ protected function isApplicable(Schema $schema): bool try { return !$schema->getTable($tableCustomItem)->hasColumn('unique_hash'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_3.php b/Migrations/Version_0_0_3.php index 709b7de35..59490da38 100644 --- a/Migrations/Version_0_0_3.php +++ b/Migrations/Version_0_0_3.php @@ -9,10 +9,7 @@ class Version_0_0_3 extends AbstractMigration { - /** - * @var string - */ - private $table = 'custom_field_option'; + private string $table = 'custom_field_option'; /** * {@inheritdoc} diff --git a/Migrations/Version_0_0_4.php b/Migrations/Version_0_0_4.php index 79be54015..b00d65ee1 100644 --- a/Migrations/Version_0_0_4.php +++ b/Migrations/Version_0_0_4.php @@ -9,10 +9,7 @@ class Version_0_0_4 extends AbstractMigration { - /** - * @var string - */ - private $table = 'custom_field_value_option'; + private string $table = 'custom_field_value_option'; /** * {@inheritdoc} diff --git a/Migrations/Version_0_0_5.php b/Migrations/Version_0_0_5.php index 623de5f4f..beeffe5d6 100644 --- a/Migrations/Version_0_0_5.php +++ b/Migrations/Version_0_0_5.php @@ -10,10 +10,7 @@ class Version_0_0_5 extends AbstractMigration { - /** - * @var string - */ - private $table = 'custom_field_value_option'; + private string $table = 'custom_field_value_option'; /** * {@inheritdoc} @@ -22,7 +19,7 @@ protected function isApplicable(Schema $schema): bool { try { return $schema->getTable($this->concatPrefix($this->table))->hasColumn('option_id'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_6.php b/Migrations/Version_0_0_6.php index 4a0ec4dcf..e7a759f1d 100644 --- a/Migrations/Version_0_0_6.php +++ b/Migrations/Version_0_0_6.php @@ -10,10 +10,7 @@ class Version_0_0_6 extends AbstractMigration { - /** - * @var string - */ - private $table = 'custom_field_option'; + private string $table = 'custom_field_option'; /** * {@inheritdoc} @@ -22,7 +19,7 @@ protected function isApplicable(Schema $schema): bool { try { return $schema->getTable($this->concatPrefix($this->table))->hasColumn('id'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_7.php b/Migrations/Version_0_0_7.php index 007d95c91..4577047fc 100644 --- a/Migrations/Version_0_0_7.php +++ b/Migrations/Version_0_0_7.php @@ -10,10 +10,7 @@ class Version_0_0_7 extends AbstractMigration { - /** - * @var string - */ - private $table = 'custom_field_option'; + private string $table = 'custom_field_option'; /** * {@inheritdoc} @@ -22,7 +19,7 @@ protected function isApplicable(Schema $schema): bool { try { return !$schema->getTable($this->concatPrefix($this->table))->hasColumn('option_order'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_8.php b/Migrations/Version_0_0_8.php index 94af2463e..a4e3cd478 100644 --- a/Migrations/Version_0_0_8.php +++ b/Migrations/Version_0_0_8.php @@ -10,10 +10,7 @@ class Version_0_0_8 extends AbstractMigration { - /** - * @var string - */ - private $table = 'custom_item_xref_custom_item'; + private string $table = 'custom_item_xref_custom_item'; /** * {@inheritdoc} @@ -22,7 +19,7 @@ protected function isApplicable(Schema $schema): bool { try { return $schema->getTable($this->concatPrefix($this->table))->hasColumn('parent_custom_item_id'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Migrations/Version_0_0_9.php b/Migrations/Version_0_0_9.php index ef82a98e6..bac270f0f 100644 --- a/Migrations/Version_0_0_9.php +++ b/Migrations/Version_0_0_9.php @@ -10,15 +10,9 @@ class Version_0_0_9 extends AbstractMigration { - /** - * @var string - */ - private $tableCustomObject = 'custom_object'; + private string $tableCustomObject = 'custom_object'; - /** - * @var string - */ - private $tableCustomField = 'custom_field'; + private string $tableCustomField = 'custom_field'; /** * {@inheritdoc} @@ -27,7 +21,7 @@ protected function isApplicable(Schema $schema): bool { try { return !$schema->getTable($this->concatPrefix($this->tableCustomObject))->hasColumn('alias'); - } catch (SchemaException $e) { + } catch (SchemaException) { return false; } } diff --git a/Model/CustomFieldModel.php b/Model/CustomFieldModel.php index 960cf3ed0..20ce79eef 100644 --- a/Model/CustomFieldModel.php +++ b/Model/CustomFieldModel.php @@ -4,38 +4,40 @@ namespace MauticPlugin\CustomObjectsBundle\Model; +use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Tools\Pagination\Paginator; use Mautic\CoreBundle\Entity\CommonRepository; +use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Helper\DateTimeHelper; use Mautic\CoreBundle\Helper\UserHelper; use Mautic\CoreBundle\Model\FormModel; +use Mautic\CoreBundle\Security\Permissions\CorePermissions; +use Mautic\CoreBundle\Translation\Translator; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Exception\ForbiddenException; use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldPermissionProvider; use MauticPlugin\CustomObjectsBundle\Repository\CustomFieldRepository; +use Psr\Log\LoggerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class CustomFieldModel extends FormModel { - /** - * @var CustomFieldRepository - */ - private $customFieldRepository; - - /** - * @var CustomFieldPermissionProvider - */ - private $permissionProvider; - public function __construct( - CustomFieldRepository $customFieldRepository, - CustomFieldPermissionProvider $permissionProvider, - UserHelper $userHelper + EntityManagerInterface $em, + CorePermissions $security, + EventDispatcherInterface $dispatcher, + UrlGeneratorInterface $router, + Translator $translator, + UserHelper $userHelper, + LoggerInterface $logger, + CoreParametersHelper $coreParametersHelper, + private CustomFieldRepository $customFieldRepository, + private CustomFieldPermissionProvider $permissionProvider, ) { - $this->customFieldRepository = $customFieldRepository; - $this->permissionProvider = $permissionProvider; - $this->userHelper = $userHelper; + parent::__construct($em, $security, $dispatcher, $router, $translator, $userHelper, $logger, $coreParametersHelper); } public function setMetadata(CustomField $entity): CustomField @@ -140,7 +142,7 @@ private function sanitizeAlias(CustomField $entity): CustomField if (empty($dirtyAlias)) { $dirtyAlias = $entity->getName(); } - $cleanAlias = $this->cleanAlias($dirtyAlias, '', false, '-'); + $cleanAlias = $this->cleanAlias($dirtyAlias, '', 0, '-'); $entity->setAlias($cleanAlias); return $entity; @@ -177,7 +179,7 @@ private function addCreatorLimit(array $args): array { try { $this->permissionProvider->isGranted('viewother'); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { if (!isset($args['filter'])) { $args['filter'] = []; } diff --git a/Model/CustomFieldOptionModel.php b/Model/CustomFieldOptionModel.php index 51bd105de..c259bfcab 100644 --- a/Model/CustomFieldOptionModel.php +++ b/Model/CustomFieldOptionModel.php @@ -8,18 +8,9 @@ class CustomFieldOptionModel { - /** - * @var EntityManager - */ - private $entityManager; - - /** - * CustomFieldOptionModel constructor. - */ public function __construct( - EntityManager $entityManager + private EntityManager $entityManager ) { - $this->entityManager = $entityManager; } /** diff --git a/Model/CustomFieldValueModel.php b/Model/CustomFieldValueModel.php index e10b92081..1bc2325b7 100644 --- a/Model/CustomFieldValueModel.php +++ b/Model/CustomFieldValueModel.php @@ -18,22 +18,10 @@ class CustomFieldValueModel { - /** - * @var EntityManager - */ - private $entityManager; - - /** - * @var ValidatorInterface - */ - private $validator; - public function __construct( - EntityManager $entityManager, - ValidatorInterface $validator + private EntityManager $entityManager, + private ValidatorInterface $validator ) { - $this->entityManager = $entityManager; - $this->validator = $validator; } /** @@ -119,7 +107,7 @@ public function getItemsListData(Collection $customFields, array $customItems): return null; } - $columns = $customFields->map(function (CustomField $customField) { + $columns = $customFields->map(function (CustomField $customField): ?string { return $customField->getLabel(); }); $data = $this->buildItemsListData($customFields->toArray(), $customItems); @@ -192,9 +180,7 @@ private function fetchValues(Collection $queries): ArrayCollection $query = implode(' UNION ALL ', $queries->toArray()); $statement = $this->entityManager->getConnection()->prepare($query); - $statement->execute(); - - return new ArrayCollection($statement->fetchAll()); + return new ArrayCollection($statement->executeQuery()->fetchAllAssociative()); } private function buildQueriesForUnion(CustomItem $customItem, Collection $customFields): Collection @@ -226,7 +212,7 @@ private function buildItemsListData(array $customFields, array $customItems): ar $result = $this->fetchItemsListData($customFields, $customItems); $result = $this->transformItemsListDataResult($result); - return array_reduce($customItems, function (array $data, CustomItem $customItem) use ($customFields, $result) { + return array_reduce($customItems, function (array $data, CustomItem $customItem) use ($customFields, $result): array { $fields = []; foreach ($customFields as $customField) { @@ -252,7 +238,7 @@ private function buildItemsListData(array $customFields, array $customItems): ar private function fetchItemsListData(array $customFields, array $customItems): array { // create a map [tableName] = [fieldId, fieldId, ...] for creating queries - $tableToCustomFieldIds = array_reduce($customFields, function (array $tables, CustomField $customField) { + $tableToCustomFieldIds = array_reduce($customFields, function (array $tables, CustomField $customField): array { $tableName = $customField->getTypeObject()->getPrefixedTableName(); if (!isset($tables[$tableName])) { @@ -276,7 +262,7 @@ private function fetchItemsListData(array $customFields, array $customItems): ar }, array_keys($tableToCustomFieldIds)); // extract item IDs - $itemIds = array_map(function (CustomItem $customItem) { + $itemIds = array_map(function (CustomItem $customItem): int { return $customItem->getId(); }, $customItems); @@ -288,7 +274,7 @@ private function fetchItemsListData(array $customFields, array $customItems): ar $types[$table] = Connection::PARAM_INT_ARRAY; } - return $this->entityManager->getConnection()->fetchAll(implode(' UNION ALL ', $queries), $params, $types); + return $this->entityManager->getConnection()->fetchAllAssociative(implode(' UNION ALL ', $queries), $params, $types); } /** @@ -297,8 +283,8 @@ private function fetchItemsListData(array $customFields, array $customItems): ar */ private function transformItemsListDataResult(array $result): array { - return array_reduce($result, function (array $result, array $row) { - $itemId = $row['custom_item_id']; + return array_reduce($result, function (array $result, array $row): array { + $itemId = $row['custom_item_id']; $fieldId = $row['custom_field_id']; if (!isset($result[$itemId])) { diff --git a/Model/CustomItemExportSchedulerModel.php b/Model/CustomItemExportSchedulerModel.php index bc09d399a..e13b353f8 100644 --- a/Model/CustomItemExportSchedulerModel.php +++ b/Model/CustomItemExportSchedulerModel.php @@ -4,12 +4,14 @@ namespace MauticPlugin\CustomObjectsBundle\Model; -use DateTimeImmutable; -use DateTimeZone; +use Doctrine\ORM\EntityManagerInterface; +use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Helper\ExportHelper; +use Mautic\CoreBundle\Helper\UserHelper; use Mautic\CoreBundle\Model\AbstractCommonModel; +use Mautic\CoreBundle\Security\Permissions\CorePermissions; +use Mautic\CoreBundle\Translation\Translator; use Mautic\EmailBundle\Helper\MailHelper; -use MauticPlugin\CustomObjectsBundle\CustomItemEvents; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomItemExportScheduler; @@ -18,9 +20,11 @@ use MauticPlugin\CustomObjectsBundle\Repository\CustomItemExportSchedulerRepository; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemXrefContactRepository; +use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class CustomItemExportSchedulerModel extends AbstractCommonModel { @@ -28,38 +32,25 @@ class CustomItemExportSchedulerModel extends AbstractCommonModel private const CUSTOM_ITEM_LIMIT = 200; private const CONTACT_LIMIT = 5000; - private ExportHelper $exportHelper; - - private MailHelper $mailHelper; - - private CustomItemRouteProvider $customItemRouteProvider; - - private CustomFieldValueModel $customFieldValueModel; - - private CustomItemXrefContactRepository $customItemXrefContactRepository; - - private CustomItemRepository $customItemRepository; - - private EventDispatcherInterface $eventDispatcher; - private string $filePath; public function __construct( - ExportHelper $exportHelper, - MailHelper $mailHelper, - CustomFieldValueModel $customFieldValueModel, - CustomItemRouteProvider $customItemRouteProvider, - CustomItemXrefContactRepository $customItemXrefContactRepository, - CustomItemRepository $customItemRepository, - EventDispatcherInterface $eventDispatcher + EntityManagerInterface $em, + CorePermissions $security, + EventDispatcherInterface $dispatcher, + UrlGeneratorInterface $router, + Translator $translator, + UserHelper $userHelper, + LoggerInterface $logger, + CoreParametersHelper $coreParametersHelper, + private ExportHelper $exportHelper, + private MailHelper $mailHelper, + private CustomFieldValueModel $customFieldValueModel, + private CustomItemRouteProvider $customItemRouteProvider, + private CustomItemXrefContactRepository $customItemXrefContactRepository, + private CustomItemRepository $customItemRepository, ) { - $this->exportHelper = $exportHelper; - $this->mailHelper = $mailHelper; - $this->customFieldValueModel = $customFieldValueModel; - $this->customItemRouteProvider = $customItemRouteProvider; - $this->customItemXrefContactRepository = $customItemXrefContactRepository; - $this->customItemRepository = $customItemRepository; - $this->eventDispatcher = $eventDispatcher; + parent::__construct($em, $security, $dispatcher, $router, $translator, $userHelper, $logger, $coreParametersHelper); } public function getRepository(): CustomItemExportSchedulerRepository @@ -79,7 +70,7 @@ public function saveEntity(int $customObjectId): CustomItemExportScheduler $customItemExportScheduler = new CustomItemExportScheduler(); $customItemExportScheduler ->setUser($this->userHelper->getUser()) - ->setScheduledDateTime(new DateTimeImmutable('now', new DateTimeZone('UTC'))) + ->setScheduledDateTime(new \DateTimeImmutable('now', new \DateTimeZone('UTC'))) ->setCustomObjectId($customObjectId); $this->em->persist($customItemExportScheduler); @@ -93,7 +84,7 @@ public function processDataAndGetExportFilePath(CustomItemExportScheduler $custo $scheduledDateTime = $customItemExportScheduler->getScheduledDateTime(); $fileName = 'custom_items_export_'.$scheduledDateTime->format(self::EXPORT_FILE_NAME_DATE_FORMAT).'.csv'; - $filePath = $this->exportHelper->getValidExportFileName($fileName, 'custom_item_export_dir'); + $filePath = $this->coreParametersHelper->get('custom_item_export_dir').'/'.$fileName; $this->filePath = $filePath; @@ -167,20 +158,12 @@ private function addCustomItemsToCsvFile(array $customFields, CustomObject $cust foreach ($customFields as $customField) { $fieldValue = $listData->getFields($customItem->getId())[$customField->getId()]->getValue(); - switch ($customField->getType()) { - case 'date': - $value = $fieldValue instanceof \DateTimeInterface ? $fieldValue->format('Y-m-d') : $fieldValue; - break; - - case 'datetime': - $value = $fieldValue instanceof \DateTimeInterface ? $fieldValue->format('Y-m-d H:i:s') : $fieldValue; - break; - - case 'multiselect': $value = is_array($fieldValue) ? implode(',', $fieldValue) : $fieldValue; - break; - - default: $value = $fieldValue; - } + $value = match ($customField->getType()) { + 'date' => $fieldValue instanceof \DateTimeInterface ? $fieldValue->format('Y-m-d') : $fieldValue, + 'datetime' => $fieldValue instanceof \DateTimeInterface ? $fieldValue->format('Y-m-d H:i:s') : $fieldValue, + 'multiselect' => is_array($fieldValue) ? implode(',', $fieldValue) : $fieldValue, + default => $fieldValue, + }; $rowData[] = $value; } @@ -206,10 +189,6 @@ private function addCustomItemsToCsvFile(array $customFields, CustomObject $cust $rowData = $savedRow; $rowData[] = implode(',', $results); - if ($this->eventDispatcher->hasListeners(CustomItemEvents::ON_PROCESSING_FILE)) { - $this->eventDispatcher->dispatch(CustomItemEvents::ON_PROCESSING_FILE); - } - fputcsv($handler, $rowData); $customItemAdded = true; } diff --git a/Model/CustomItemImportModel.php b/Model/CustomItemImportModel.php index 64d1d6266..10836f344 100644 --- a/Model/CustomItemImportModel.php +++ b/Model/CustomItemImportModel.php @@ -4,40 +4,39 @@ namespace MauticPlugin\CustomObjectsBundle\Model; -use Doctrine\ORM\EntityManager; +use Doctrine\ORM\EntityManagerInterface; +use Mautic\CoreBundle\Helper\CoreParametersHelper; +use Mautic\CoreBundle\Helper\UserHelper; use Mautic\CoreBundle\Model\FormModel; -use Mautic\CoreBundle\Templating\Helper\FormatterHelper; +use Mautic\CoreBundle\Security\Permissions\CorePermissions; +use Mautic\CoreBundle\Translation\Translator; +use Mautic\CoreBundle\Twig\Helper\FormatterHelper; use Mautic\LeadBundle\Entity\Import; +use Mautic\LeadBundle\Entity\Lead; use Mautic\UserBundle\Entity\User; +use MauticPlugin\CustomObjectsBundle\DTO\ImportLogDTO; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; +use Psr\Log\LoggerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class CustomItemImportModel extends FormModel { - /** - * @var EntityManager - */ - private $entityManager; - - /** - * @var CustomItemModel - */ - private $customItemModel; - - /** - * @var FormatterHelper - */ - private $formatterHelper; - public function __construct( - EntityManager $entityManager, - CustomItemModel $customItemModel, - FormatterHelper $formatterHelper + EntityManagerInterface $em, + CorePermissions $security, + EventDispatcherInterface $dispatcher, + UrlGeneratorInterface $router, + Translator $translator, + UserHelper $userHelper, + LoggerInterface $logger, + CoreParametersHelper $coreParametersHelper, + private CustomItemModel $customItemModel, + private FormatterHelper $formatterHelper, ) { - $this->entityManager = $entityManager; - $this->customItemModel = $customItemModel; - $this->formatterHelper = $formatterHelper; + parent::__construct($em, $security, $dispatcher, $router, $translator, $userHelper, $logger, $coreParametersHelper); } /** @@ -45,7 +44,7 @@ public function __construct( * * @return bool updated = true, inserted = false */ - public function import(Import $import, array $rowData, CustomObject $customObject): bool + public function import(Import $import, array $rowData, CustomObject $customObject, ImportLogDTO $importLogDto = null): bool { $matchedFields = $import->getMatchedFields(); $customItem = $this->getCustomItem($import, $customObject, $rowData); @@ -80,7 +79,7 @@ public function import(Import $import, array $rowData, CustomObject $customObjec try { $customFieldValue = $customItem->findCustomFieldValueForFieldId((int) $customFieldId); - } catch (NotFoundException $e) { + } catch (NotFoundException) { $customFieldValue = $customItem->createNewCustomFieldValueByFieldId((int) $customFieldId, $csvValue); } @@ -94,7 +93,7 @@ public function import(Import $import, array $rowData, CustomObject $customObjec $merged = true; } - $this->linkContacts($customItem, $contactIds); + $this->linkContacts($customItem, $contactIds, $importLogDto); return $merged; } @@ -102,14 +101,25 @@ public function import(Import $import, array $rowData, CustomObject $customObjec /** * @param int[] $contactIds */ - private function linkContacts(CustomItem $customItem, array $contactIds): CustomItem + private function linkContacts(CustomItem $customItem, array $contactIds, ?ImportLogDTO $importLogDto): void { foreach ($contactIds as $contactId) { - $xref = $this->customItemModel->linkEntity($customItem, 'contact', $contactId); + $leadRepository = $this->em->getRepository(Lead::class); + if (method_exists($leadRepository, 'exists') && !$leadRepository->exists((string) $contactId)) { + if ($importLogDto) { + $importLogDto->addWarning( + $this->translator->trans('custom.item.import.invalid.contactid.for.link', [ + '%contactId%' => $contactId, + '%customItemId%' => $customItem->getId(), + ]) + ); + } + continue; + } + + $xref = $this->customItemModel->linkEntity($customItem, 'contact', (int) $contactId); $customItem->addContactReference($xref); } - - return $customItem; } private function setOwner(Import $import, CustomItem $customItem): CustomItem @@ -118,7 +128,7 @@ private function setOwner(Import $import, CustomItem $customItem): CustomItem if ($owner) { /** @var User $user */ - $user = $this->entityManager->find(User::class, $owner); + $user = $this->em->find(User::class, $owner); $customItem->setCreatedBy($user); } @@ -143,7 +153,7 @@ private function getCustomItem(Import $import, CustomObject $customObject, array try { $customItem = $this->customItemModel->fetchEntity((int) $rowData[$idKey]); $customItem = $this->customItemModel->populateCustomFields($customItem); - } catch (NotFoundException $e) { + } catch (NotFoundException) { } } diff --git a/Model/CustomItemModel.php b/Model/CustomItemModel.php index 626db817f..b1625c77e 100644 --- a/Model/CustomItemModel.php +++ b/Model/CustomItemModel.php @@ -5,13 +5,16 @@ namespace MauticPlugin\CustomObjectsBundle\Model; use Doctrine\DBAL\Query\QueryBuilder as DbalQueryBuilder; -use Doctrine\ORM\EntityManager; +use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\QueryBuilder; use Mautic\CoreBundle\Doctrine\Helper\FulltextKeyword; use Mautic\CoreBundle\Entity\CommonRepository; +use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Helper\DateTimeHelper; use Mautic\CoreBundle\Helper\UserHelper; use Mautic\CoreBundle\Model\FormModel; +use Mautic\CoreBundle\Security\Permissions\CorePermissions; +use Mautic\CoreBundle\Translation\Translator; use MauticPlugin\CustomObjectsBundle\CustomItemEvents; use MauticPlugin\CustomObjectsBundle\DTO\CustomItemFieldListData; use MauticPlugin\CustomObjectsBundle\DTO\TableConfig; @@ -31,53 +34,28 @@ use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository; +use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; -use UnexpectedValueException; class CustomItemModel extends FormModel { - /** - * @var EntityManager - */ - private $entityManager; - - /** - * @var CustomItemRepository - */ - private $customItemRepository; - - /** - * @var CustomItemPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomFieldValueModel - */ - private $customFieldValueModel; - - /** - * @var ValidatorInterface - */ - private $validator; - public function __construct( - EntityManager $entityManager, - CustomItemRepository $customItemRepository, - CustomItemPermissionProvider $permissionProvider, - UserHelper $userHelper, - CustomFieldValueModel $customFieldValueModel, + EntityManagerInterface $em, + CorePermissions $security, EventDispatcherInterface $dispatcher, - ValidatorInterface $validator + UrlGeneratorInterface $router, + Translator $translator, + UserHelper $userHelper, + LoggerInterface $logger, + CoreParametersHelper $coreParametersHelper, + private CustomItemRepository $customItemRepository, + private CustomItemPermissionProvider $permissionProvider, + private CustomFieldValueModel $customFieldValueModel, + private ValidatorInterface $validator, ) { - $this->entityManager = $entityManager; - $this->customItemRepository = $customItemRepository; - $this->permissionProvider = $permissionProvider; - $this->userHelper = $userHelper; - $this->customFieldValueModel = $customFieldValueModel; - $this->dispatcher = $dispatcher; - $this->validator = $validator; + parent::__construct($em, $security, $dispatcher, $router, $translator, $userHelper, $logger, $coreParametersHelper); } public function save(CustomItem $customItem, bool $dryRun = false): CustomItem @@ -102,18 +80,18 @@ public function save(CustomItem $customItem, bool $dryRun = false): CustomItem throw new InvalidValueException($errors->get(0)->getMessage()); } - $this->dispatcher->dispatch(CustomItemEvents::ON_CUSTOM_ITEM_PRE_SAVE, new CustomItemEvent($customItem, $customItem->isNew())); + $this->dispatcher->dispatch(new CustomItemEvent($customItem, $customItem->isNew()), CustomItemEvents::ON_CUSTOM_ITEM_PRE_SAVE); if (!$dryRun) { if ($customItem->isNew()) { // Custom item is new so we need to upsert it to atomically find whether it exists based on unique fields or not. - $this->entityManager->detach($customItem); + $this->em->detach($customItem); $this->customItemRepository->upsert($customItem); // We need to re-attach the entity to the entity manager so that it can be saved by the rest of the code. $customFieldValues = $customItem->getCustomFieldValues(); - $hasBeenUpdated = $customItem->hasBeenUpdated(); - $hasBeenInserted = $customItem->hasBeenInserted(); + $hasBeenUpdated = $customItem->hasBeenUpdated(); + $hasBeenInserted = $customItem->hasBeenInserted(); $customItem = $this->fetchEntity($customItem->getId()); $customItem->setHasBeenUpdated($hasBeenUpdated); @@ -124,8 +102,8 @@ public function save(CustomItem $customItem, bool $dryRun = false): CustomItem $customItem->addCustomFieldValue($customFieldValue); } } else { - $this->entityManager->persist($customItem); - $this->entityManager->flush(); + $this->em->persist($customItem); + $this->em->flush(); } $customItem->getCustomFieldValues()->map( @@ -134,7 +112,7 @@ public function save(CustomItem $customItem, bool $dryRun = false): CustomItem $customItem->recordCustomFieldValueChanges(); - $this->dispatcher->dispatch(CustomItemEvents::ON_CUSTOM_ITEM_POST_SAVE, new CustomItemEvent($customItem, $customItem->isNew())); + $this->dispatcher->dispatch(new CustomItemEvent($customItem, $customItem->isNew()), CustomItemEvents::ON_CUSTOM_ITEM_POST_SAVE); } return $customItem; @@ -157,54 +135,54 @@ public function unlockEntity($entity, $extra = null): void } /** - * @throws UnexpectedValueException + * @throws \UnexpectedValueException */ public function linkEntity(CustomItem $customItem, string $entityType, int $entityId): CustomItemXrefInterface { $event = new CustomItemXrefEntityDiscoveryEvent($customItem, $entityType, $entityId); - $this->dispatcher->dispatch(CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY, $event); + $this->dispatcher->dispatch($event, CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY); if (!$event->getXrefEntity() instanceof CustomItemXrefInterface) { - throw new UnexpectedValueException("Entity {$entityType} was not able to be linked to {$customItem->getName()} ({$customItem->getId()})"); + throw new \UnexpectedValueException("Entity {$entityType} was not able to be linked to {$customItem->getName()} ({$customItem->getId()})"); } - $this->dispatcher->dispatch(CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY, new CustomItemXrefEntityEvent($event->getXrefEntity())); + $this->dispatcher->dispatch(new CustomItemXrefEntityEvent($event->getXrefEntity()), CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY); return $event->getXrefEntity(); } /** - * @throws UnexpectedValueException + * @throws \UnexpectedValueException */ public function unlinkEntity(CustomItem $customItem, string $entityType, int $entityId): CustomItemXrefInterface { $event = new CustomItemXrefEntityDiscoveryEvent($customItem, $entityType, $entityId); - $this->dispatcher->dispatch(CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY, $event); + $this->dispatcher->dispatch($event, CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY); if (!$event->getXrefEntity() instanceof CustomItemXrefInterface) { - throw new UnexpectedValueException("Entity {$entityType} was not able to be unlinked from {$customItem->getName()} ({$customItem->getId()})"); + throw new \UnexpectedValueException("Entity {$entityType} was not able to be unlinked from {$customItem->getName()} ({$customItem->getId()})"); } - $this->dispatcher->dispatch(CustomItemEvents::ON_CUSTOM_ITEM_UNLINK_ENTITY, new CustomItemXrefEntityEvent($event->getXrefEntity())); + $this->dispatcher->dispatch(new CustomItemXrefEntityEvent($event->getXrefEntity()), CustomItemEvents::ON_CUSTOM_ITEM_UNLINK_ENTITY); return $event->getXrefEntity(); } public function delete(CustomItem $customItem): void { - //take note of ID before doctrine wipes it out + // take note of ID before doctrine wipes it out $id = $customItem->getId(); $event = new CustomItemEvent($customItem); - $this->dispatcher->dispatch(CustomItemEvents::ON_CUSTOM_ITEM_PRE_DELETE, $event); + $this->dispatcher->dispatch($event, CustomItemEvents::ON_CUSTOM_ITEM_PRE_DELETE); - $this->entityManager->remove($customItem); - $this->entityManager->flush(); + $this->em->remove($customItem); + $this->em->flush(); - //set the id for use in events + // set the id for use in events $customItem->deletedId = $id; - $this->dispatcher->dispatch(CustomItemEvents::ON_CUSTOM_ITEM_POST_DELETE, $event); + $this->dispatcher->dispatch($event, CustomItemEvents::ON_CUSTOM_ITEM_POST_DELETE); } /** @@ -232,8 +210,8 @@ public function getTableData(TableConfig $tableConfig): array $queryBuilder = $this->createListOrmQueryBuilder($tableConfig); $this->dispatcher->dispatch( - CustomItemEvents::ON_CUSTOM_ITEM_LIST_ORM_QUERY, - new CustomItemListQueryEvent($queryBuilder, $tableConfig) + new CustomItemListQueryEvent($queryBuilder, $tableConfig), + CustomItemEvents::ON_CUSTOM_ITEM_LIST_ORM_QUERY ); return $queryBuilder->getQuery()->getResult(); @@ -247,11 +225,11 @@ public function getArrayTableData(TableConfig $tableConfig): array $queryBuilder = $this->createListDbalQueryBuilder($tableConfig); $this->dispatcher->dispatch( - CustomItemEvents::ON_CUSTOM_ITEM_LIST_DBAL_QUERY, - new CustomItemListDbalQueryEvent($queryBuilder, $tableConfig) + new CustomItemListDbalQueryEvent($queryBuilder, $tableConfig), + CustomItemEvents::ON_CUSTOM_ITEM_LIST_DBAL_QUERY ); - return $queryBuilder->execute()->fetchAll(); + return $queryBuilder->execute()->fetchAllAssociative(); } public function getCountForTable(TableConfig $tableConfig): int @@ -263,8 +241,8 @@ public function getCountForTable(TableConfig $tableConfig): int $queryBuilder->resetDQLPart('orderBy'); $this->dispatcher->dispatch( - CustomItemEvents::ON_CUSTOM_ITEM_LIST_ORM_QUERY, - new CustomItemListQueryEvent($queryBuilder, $tableConfig) + new CustomItemListQueryEvent($queryBuilder, $tableConfig), + CustomItemEvents::ON_CUSTOM_ITEM_LIST_ORM_QUERY ); return (int) $queryBuilder->getQuery()->getSingleScalarResult(); @@ -280,8 +258,8 @@ public function getLookupData(TableConfig $tableConfig): array $queryBuilder->select("{$rootAlias}.name as value, {$rootAlias}.id"); $this->dispatcher->dispatch( - CustomItemEvents::ON_CUSTOM_ITEM_LOOKUP_QUERY, - new CustomItemListQueryEvent($queryBuilder, $tableConfig) + new CustomItemListQueryEvent($queryBuilder, $tableConfig), + CustomItemEvents::ON_CUSTOM_ITEM_LOOKUP_QUERY ); $rows = $queryBuilder->getQuery()->getArrayResult(); @@ -316,17 +294,11 @@ public function populateCustomFields(CustomItem $customItem): CustomItem */ public function getFieldListData(CustomObject $customObject, array $customItems, string $filterEntityType): ?CustomItemFieldListData { - switch ($filterEntityType) { - case 'customItem': - $customFields = $customObject->getFieldsShowInCustomObjectDetailList(); - break; - case 'contact': - $customFields = $customObject->getFieldsShowInContactDetailList(); - break; - default: - $customFields = $customObject->getPublishedFields(); - break; - } + $customFields = match ($filterEntityType) { + 'customItem' => $customObject->getFieldsShowInCustomObjectDetailList(), + 'contact' => $customObject->getFieldsShowInContactDetailList(), + default => $customObject->getPublishedFields(), + }; return $this->customFieldValueModel->getItemsListData($customFields, $customItems); } @@ -351,7 +323,7 @@ public function getPermissionBase(): string } /** - * @throws UnexpectedValueException + * @throws \UnexpectedValueException */ private function createListOrmQueryBuilder(TableConfig $tableConfig): QueryBuilder { @@ -359,7 +331,7 @@ private function createListOrmQueryBuilder(TableConfig $tableConfig): QueryBuild $customObjectId = $tableConfig->getParameter('customObjectId'); $search = $tableConfig->getParameter('search'); - $queryBuilder = $this->entityManager->createQueryBuilder(); + $queryBuilder = $this->em->createQueryBuilder(); $queryBuilder = $tableConfig->configureOrmQueryBuilder($queryBuilder); $queryBuilder->select(CustomItem::TABLE_ALIAS); @@ -375,14 +347,14 @@ private function createListOrmQueryBuilder(TableConfig $tableConfig): QueryBuild } /** - * @throws UnexpectedValueException + * @throws \UnexpectedValueException */ private function createListDbalQueryBuilder(TableConfig $tableConfig): DbalQueryBuilder { $this->validateTableConfig($tableConfig); $customObjectId = $tableConfig->getParameter('customObjectId'); - $queryBuilder = $this->entityManager->getConnection()->createQueryBuilder(); + $queryBuilder = $this->em->getConnection()->createQueryBuilder(); $queryBuilder = $tableConfig->configureDbalQueryBuilder($queryBuilder); $queryBuilder->select(CustomItem::TABLE_ALIAS.'.*'); @@ -394,12 +366,12 @@ private function createListDbalQueryBuilder(TableConfig $tableConfig): DbalQuery } /** - * @throws UnexpectedValueException + * @throws \UnexpectedValueException */ private function validateTableConfig(TableConfig $tableConfig): void { if (empty($tableConfig->getParameter('customObjectId'))) { - throw new UnexpectedValueException("customObjectId cannot be empty. It's required for permission management"); + throw new \UnexpectedValueException("customObjectId cannot be empty. It's required for permission management"); } } @@ -421,7 +393,7 @@ private function applyOwnerFilter($queryBuilder, int $customObjectId) try { $this->permissionProvider->isGranted('viewother', $customObjectId); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { $queryBuilder->andWhere(CustomItem::TABLE_ALIAS.'.createdBy', $user->getId()); } @@ -430,12 +402,12 @@ private function applyOwnerFilter($queryBuilder, int $customObjectId) private function applySearchFilter(QueryBuilder $queryBuilder, string $search): void { - $valueTextBuilder = $this->entityManager->createQueryBuilder(); + $valueTextBuilder = $this->em->createQueryBuilder(); $valueTextBuilder->select('IDENTITY(ValueText.customItem)'); $valueTextBuilder->from(CustomFieldValueText::class, 'ValueText'); $valueTextBuilder->andWhere('MATCH (ValueText.value) AGAINST (:search BOOLEAN) > 0'); - $valueOptionBuilder = $this->entityManager->createQueryBuilder(); + $valueOptionBuilder = $this->em->createQueryBuilder(); $valueOptionBuilder->select('IDENTITY(ValueOption.customItem)'); $valueOptionBuilder->from(CustomFieldValueOption::class, 'ValueOption'); $valueOptionBuilder->andWhere('MATCH (ValueOption.value) AGAINST (:search BOOLEAN) > 0'); diff --git a/Model/CustomItemXrefContactModel.php b/Model/CustomItemXrefContactModel.php index 6d9f378d5..9ae36f3a2 100644 --- a/Model/CustomItemXrefContactModel.php +++ b/Model/CustomItemXrefContactModel.php @@ -4,39 +4,23 @@ namespace MauticPlugin\CustomObjectsBundle\Model; -use DateTime; -use Doctrine\ORM\EntityManager; use Mautic\CoreBundle\Helper\Chart\ChartQuery; use Mautic\CoreBundle\Helper\Chart\LineChart; use Mautic\CoreBundle\Model\FormModel; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; -use Symfony\Component\Translation\TranslatorInterface; class CustomItemXrefContactModel extends FormModel { - /** - * @var EntityManager - */ - private $entityManager; - - public function __construct( - EntityManager $entityManager, - TranslatorInterface $translator - ) { - $this->entityManager = $entityManager; - $this->translator = $translator; - } - /** * @return mixed[] */ public function getLinksLineChartData( - DateTime $from, - DateTime $to, + \DateTime $from, + \DateTime $to, CustomItem $customItem ): array { $chart = new LineChart(null, $from, $to); - $query = new ChartQuery($this->entityManager->getConnection(), $from, $to); + $query = new ChartQuery($this->em->getConnection(), $from, $to); $links = $query->fetchTimeData( 'custom_item_xref_contact', 'date_added', diff --git a/Model/CustomObjectModel.php b/Model/CustomObjectModel.php index fd6d1eed0..04de8371b 100644 --- a/Model/CustomObjectModel.php +++ b/Model/CustomObjectModel.php @@ -4,16 +4,18 @@ namespace MauticPlugin\CustomObjectsBundle\Model; -use Doctrine\ORM\EntityManager; +use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\Tools\Pagination\Paginator; use Mautic\CoreBundle\Entity\CommonRepository; use Mautic\CoreBundle\Helper\Chart\ChartQuery; use Mautic\CoreBundle\Helper\Chart\LineChart; +use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Helper\DateTimeHelper; use Mautic\CoreBundle\Helper\UserHelper; use Mautic\CoreBundle\Model\FormModel; -use Mautic\LeadBundle\Model\ListModel; +use Mautic\CoreBundle\Security\Permissions\CorePermissions; +use Mautic\CoreBundle\Translation\Translator; use MauticPlugin\CustomObjectsBundle\CustomObjectEvents; use MauticPlugin\CustomObjectsBundle\DTO\TableConfig; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; @@ -23,51 +25,26 @@ use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectPermissionProvider; use MauticPlugin\CustomObjectsBundle\Repository\CustomObjectRepository; +use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class CustomObjectModel extends FormModel { - /** - * @var EntityManager - */ - private $entityManager; - - /** - * @var CustomObjectRepository - */ - private $customObjectRepository; - - /** - * @var CustomObjectPermissionProvider - */ - private $permissionProvider; - - /** - * @var CustomFieldModel - */ - private $customFieldModel; - - /** - * @var ListModel - */ - private $listModel; - public function __construct( - EntityManager $entityManager, - CustomObjectRepository $customObjectRepository, - CustomObjectPermissionProvider $permissionProvider, - UserHelper $userHelper, - CustomFieldModel $customFieldModel, + EntityManagerInterface $em, + CorePermissions $security, EventDispatcherInterface $dispatcher, - ListModel $listModel + UrlGeneratorInterface $router, + Translator $translator, + UserHelper $userHelper, + LoggerInterface $logger, + CoreParametersHelper $coreParametersHelper, + private CustomObjectRepository $customObjectRepository, + private CustomObjectPermissionProvider $permissionProvider, + private CustomFieldModel $customFieldModel, ) { - $this->entityManager = $entityManager; - $this->customObjectRepository = $customObjectRepository; - $this->permissionProvider = $permissionProvider; - $this->userHelper = $userHelper; - $this->customFieldModel = $customFieldModel; - $this->dispatcher = $dispatcher; - $this->listModel = $listModel; + parent::__construct($em, $security, $dispatcher, $router, $translator, $userHelper, $logger, $coreParametersHelper); } public function save(CustomObject $customObject): CustomObject @@ -97,12 +74,12 @@ public function save(CustomObject $customObject): CustomObject $this->setCustomFieldsMetadata($customObject); - $this->dispatcher->dispatch(CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_SAVE, $event); + $this->dispatcher->dispatch($event, CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_SAVE); - $this->entityManager->persist($customObject); - $this->entityManager->flush(); + $this->em->persist($customObject); + $this->em->flush(); - $this->dispatcher->dispatch(CustomObjectEvents::ON_CUSTOM_OBJECT_POST_SAVE, $event); + $this->dispatcher->dispatch($event, CustomObjectEvents::ON_CUSTOM_OBJECT_POST_SAVE); return $customObject; } @@ -112,14 +89,14 @@ public function delete(CustomObject $customObject): void // Take note of ID before doctrine wipes it out $id = $customObject->getId(); $event = new CustomObjectEvent($customObject); - $this->dispatcher->dispatch(CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_DELETE, $event); + $this->dispatcher->dispatch($event, CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_DELETE); - $this->entityManager->remove($customObject); - $this->entityManager->flush(); + $this->em->remove($customObject); + $this->em->flush(); // Set the id for use in events $customObject->deletedId = $id; - $this->dispatcher->dispatch(CustomObjectEvents::ON_CUSTOM_OBJECT_POST_DELETE, $event); + $this->dispatcher->dispatch($event, CustomObjectEvents::ON_CUSTOM_OBJECT_POST_DELETE); } /** @@ -211,7 +188,7 @@ public function removeCustomFieldById(CustomObject $customObject, int $customFie foreach ($customObject->getCustomFields() as $customField) { if ($customField->getId() === $customFieldId) { $customObject->removeCustomField($customField); - if ($this->entityManager->contains($customField)) { + if ($this->em->contains($customField)) { // We need to ensure that field exists when cloning CO with deleted fields $this->customFieldModel->deleteEntity($customField); } @@ -241,7 +218,7 @@ public function getPermissionBase(): string public function getItemsLineChartData(\DateTime $from, \DateTime $to, CustomObject $customObject): array { $chart = new LineChart(null, $from, $to); - $query = new ChartQuery($this->entityManager->getConnection(), $from, $to); + $query = new ChartQuery($this->em->getConnection(), $from, $to); $items = $query->fetchTimeData('custom_item', 'date_added', ['custom_object_id' => $customObject->getId()]); $chart->setDataset($this->translator->trans('custom.object.created.items'), $items); @@ -250,7 +227,7 @@ public function getItemsLineChartData(\DateTime $from, \DateTime $to, CustomObje private function createListQueryBuilder(TableConfig $tableConfig): QueryBuilder { - $queryBuilder = $this->entityManager->createQueryBuilder(); + $queryBuilder = $this->em->createQueryBuilder(); $queryBuilder = $tableConfig->configureOrmQueryBuilder($queryBuilder); $queryBuilder->select(CustomObject::TABLE_ALIAS); $queryBuilder->from(CustomObject::class, CustomObject::TABLE_ALIAS); @@ -271,7 +248,7 @@ private function sanitizeAlias(CustomObject $entity): CustomObject if (empty($dirtyAlias)) { $dirtyAlias = $entity->getName(); } - $cleanAlias = $this->cleanAlias($dirtyAlias, '', false, '-'); + $cleanAlias = $this->cleanAlias($dirtyAlias, '', 0, '-'); $entity->setAlias($cleanAlias); return $entity; @@ -313,7 +290,7 @@ private function addCreatorLimit(array $args): array try { $this->permissionProvider->isGranted('viewother'); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { if (!isset($args['filter'])) { $args['filter'] = []; } @@ -339,7 +316,7 @@ private function applyOwnerFilter(QueryBuilder $queryBuilder): QueryBuilder { try { $this->permissionProvider->isGranted('viewother'); - } catch (ForbiddenException $e) { + } catch (ForbiddenException) { $queryBuilder->andWhere(CustomObject::TABLE_ALIAS.'.createdBy', $this->userHelper->getUser()->getId()); } @@ -363,7 +340,7 @@ public function getMasterCustomObjects(): array { return array_filter( $this->fetchAllPublishedEntities(), - function ($item) { + function ($item): bool { $type = $item->getType(); return CustomObject::TYPE_MASTER === $type || null === $type; diff --git a/Provider/AbstractPermissionProvider.php b/Provider/AbstractPermissionProvider.php index 680b239b5..723687d40 100644 --- a/Provider/AbstractPermissionProvider.php +++ b/Provider/AbstractPermissionProvider.php @@ -12,14 +12,8 @@ abstract class AbstractPermissionProvider { public const BASE = 'undefined'; - /** - * @var CorePermissions - */ - private $corePermissions; - - public function __construct(CorePermissions $corePermissions) + public function __construct(private CorePermissions $corePermissions) { - $this->corePermissions = $corePermissions; } /** @@ -40,7 +34,7 @@ public function hasEntityAccess(string $permission, FormEntity $entity): void if (!$this->corePermissions->hasEntityAccess(static::BASE.$permission.'own', static::BASE.$permission.'other', $entity->getCreatedBy())) { $entityId = method_exists($entity, 'getId') ? $entity->getId() : null; - throw new ForbiddenException($permission, get_class($entity), $entityId); + throw new ForbiddenException($permission, $entity::class, $entityId); } } diff --git a/Provider/ConfigProvider.php b/Provider/ConfigProvider.php index 94b5e8f0c..62549c52b 100644 --- a/Provider/ConfigProvider.php +++ b/Provider/ConfigProvider.php @@ -14,14 +14,10 @@ class ConfigProvider public const CONFIG_PARAM_ENABLED = 'custom_objects_enabled'; public const CONFIG_PARAM_ITEM_VALUE_TO_CONTACT_RELATION_LIMIT = 'custom_object_item_value_to_contact_relation_limit'; - /** - * @var CoreParametersHelper - */ - private $coreParametersHelper; + public const CONFIG_PARAM_ITEM_VALUE_TO_CONTACT_RELATION_DEFAULT_LIMIT = 3; - public function __construct(CoreParametersHelper $coreParametersHelper) + public function __construct(private CoreParametersHelper $coreParametersHelper) { - $this->coreParametersHelper = $coreParametersHelper; } /** @@ -31,4 +27,14 @@ public function pluginIsEnabled(): bool { return (bool) $this->coreParametersHelper->get(self::CONFIG_PARAM_ENABLED, true); } + + public function isCustomObjectMergeFilterEnabled(): bool + { + return $this->coreParametersHelper->get('custom_object_merge_filter', false) + && (0 === (int) $this->coreParametersHelper->get( + self::CONFIG_PARAM_ITEM_VALUE_TO_CONTACT_RELATION_LIMIT, + self::CONFIG_PARAM_ITEM_VALUE_TO_CONTACT_RELATION_DEFAULT_LIMIT + ) + ); + } } diff --git a/Provider/CustomFieldRouteProvider.php b/Provider/CustomFieldRouteProvider.php index 3463ee768..8ee50516c 100644 --- a/Provider/CustomFieldRouteProvider.php +++ b/Provider/CustomFieldRouteProvider.php @@ -12,14 +12,8 @@ class CustomFieldRouteProvider public const ROUTE_SAVE = 'mautic_custom_field_save'; - /** - * @var RouterInterface - */ - private $router; - - public function __construct(RouterInterface $router) + public function __construct(private RouterInterface $router) { - $this->router = $router; } public function buildSaveRoute(string $fieldType, ?int $id = null, ?int $objectId = null, ?int $panelCount = null, ?int $panelId = null): string diff --git a/Provider/CustomFieldTypeProvider.php b/Provider/CustomFieldTypeProvider.php index 57569fe38..45e1cf916 100644 --- a/Provider/CustomFieldTypeProvider.php +++ b/Provider/CustomFieldTypeProvider.php @@ -13,7 +13,7 @@ class CustomFieldTypeProvider /** * @var CustomFieldTypeInterface[] */ - private $customFieldTypes = []; + private array $customFieldTypes = []; /** * Builds the list of custom field type objects. diff --git a/Provider/CustomItemPermissionProvider.php b/Provider/CustomItemPermissionProvider.php index c756e1da8..b681524c4 100644 --- a/Provider/CustomItemPermissionProvider.php +++ b/Provider/CustomItemPermissionProvider.php @@ -11,14 +11,8 @@ class CustomItemPermissionProvider { - /** - * @var CorePermissions - */ - private $corePermissions; - - public function __construct(CorePermissions $corePermissions) + public function __construct(private CorePermissions $corePermissions) { - $this->corePermissions = $corePermissions; } /** diff --git a/Provider/CustomItemRouteProvider.php b/Provider/CustomItemRouteProvider.php index 9ad8c09d2..3010b86c7 100644 --- a/Provider/CustomItemRouteProvider.php +++ b/Provider/CustomItemRouteProvider.php @@ -51,14 +51,8 @@ class CustomItemRouteProvider public const ROUTE_CONTACT_LIST = 'mautic_custom_item_contacts'; - /** - * @var RouterInterface - */ - private $router; - - public function __construct(RouterInterface $router) + public function __construct(private RouterInterface $router) { - $this->router = $router; } public function buildListRoute(int $objectId, int $page = 1, string $filterEntityType = null, int $filterEntityId = null, array $parameters = []): string diff --git a/Provider/CustomObjectRouteProvider.php b/Provider/CustomObjectRouteProvider.php index 954ecd293..63aa4ae6a 100644 --- a/Provider/CustomObjectRouteProvider.php +++ b/Provider/CustomObjectRouteProvider.php @@ -26,14 +26,8 @@ class CustomObjectRouteProvider public const ROUTE_LINK = 'mautic_custom_object_link'; - /** - * @var RouterInterface - */ - private $router; - - public function __construct(RouterInterface $router) + public function __construct(private RouterInterface $router) { - $this->router = $router; } public function buildListRoute(int $page = 1): string @@ -56,9 +50,6 @@ public function buildNewRoute(): string return $this->router->generate(static::ROUTE_NEW); } - /** - * @param int $id - */ public function buildEditRoute(?int $id = null): string { return $this->router->generate(static::ROUTE_EDIT, ['objectId' => $id]); diff --git a/Provider/SessionProvider.php b/Provider/SessionProvider.php index f06c91d36..e6790c6e1 100644 --- a/Provider/SessionProvider.php +++ b/Provider/SessionProvider.php @@ -33,26 +33,8 @@ class SessionProvider */ private const KEY_FILTER = 'filter'; - /** - * @var Session - */ - private $session; - - /** - * @var int - */ - private $defaultPageLimit; - - /** - * @var string - */ - private $namespace; - - public function __construct(Session $session, string $namespace, int $defaultPageLimit) + public function __construct(private Session $session, private string $namespace, private int $defaultPageLimit) { - $this->session = $session; - $this->namespace = $namespace; - $this->defaultPageLimit = $defaultPageLimit; } public function getNamespace(): string diff --git a/Provider/SessionProviderFactory.php b/Provider/SessionProviderFactory.php index 63a302484..7bbdb5e16 100644 --- a/Provider/SessionProviderFactory.php +++ b/Provider/SessionProviderFactory.php @@ -9,20 +9,8 @@ class SessionProviderFactory { - /** - * @var Session - */ - private $session; - - /** - * @var CoreParametersHelper - */ - private $coreParametersHelper; - - public function __construct(Session $session, CoreParametersHelper $coreParametersHelper) + public function __construct(private Session $session, private CoreParametersHelper $coreParametersHelper) { - $this->session = $session; - $this->coreParametersHelper = $coreParametersHelper; } public function createObjectProvider(): SessionProvider diff --git a/README.md b/README.md index 972c611a5..3cdf2dd66 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,12 @@ You'll be able to - filter Segments by values in the Custom Objects - create Campaign conditions based on the values in the Custom Objects +## Workflow Update + +Until Github Actions' CI/CD are in place, we request to developers to: +1. Merge their unreviewed and unapproved PRs to `development` branch. +2. Merge their reviewed and approved PRs to `beta` branch. + ## Glossary - `Custom Field` represents one piece of information. Example: Price, Description, Color @@ -48,6 +54,21 @@ See [Wiki](https://github.com/acquia/mc-cs-plugin-custom-objects/wiki) The plugin has currently test coverage of 91%. Each new PR must be covered by tests to be considered to be merged. To run the tests execute `composer test -- --filter CustomObjects` from the Mautic root dir. +## Static Analysis + +PHPSTAN is used for static analysis. Here is how to run it locally from the Mautic's root dir: +``` +bin/phpstan --configuration=plugins/CustomObjectsBundle/phpstan.neon +``` + +This plugin has its own PHPSTAN configuration because there is too big tech debt pile already and so it must have its own PHPSTAN baseline file. + +The tech debt is visible in the phpstan-baseline.neon file and can be regenerated with: +``` +bin/phpstan --configuration=plugins/CustomObjectsBundle/phpstan.neon --generate-baseline=plugins/CustomObjectsBundle/phpstan-baseline.neon && sed -i 's/plugins\/CustomObjectsBundle\//g' plugins/CustomObjectsBundle/phpstan-neon.php +``` +Please do not add more tech debt on this pile. Fix all the new PHPSTAN errors and possibly some old ones with your code changes. + ## License Copyright (C) 2022 Acquia, Inc. diff --git a/Report/ReportColumnsBuilder.php b/Report/ReportColumnsBuilder.php index 12e403f94..1b131b6b3 100644 --- a/Report/ReportColumnsBuilder.php +++ b/Report/ReportColumnsBuilder.php @@ -14,14 +14,9 @@ class ReportColumnsBuilder public const DEFAULT_COLUMN_TYPE = 'string'; /** - * @var CustomObject + * @var mixed[] */ - private $customObject; - - /** - * @var array - */ - private $columns = []; + private array $columns = []; /** * @var callable @@ -37,9 +32,8 @@ class ReportColumnsBuilder 'datetime' => 'datetime', ]; - public function __construct(CustomObject $customObject) + public function __construct(private CustomObject $customObject) { - $this->customObject = $customObject; } private function buildColumns(): void diff --git a/Repository/CustomCommonRepository.php b/Repository/CustomCommonRepository.php new file mode 100644 index 000000000..8d7c30e2b --- /dev/null +++ b/Repository/CustomCommonRepository.php @@ -0,0 +1,18 @@ +where(CustomItem::TABLE_ALIAS.'.customObject = :customObjectId'); $queryBuilder->setParameter('customObjectId', $customObjectId); $queryBuilder->setMaxResults(1); + return (int) $queryBuilder->getQuery()->getSingleScalarResult(); } diff --git a/Repository/CustomItemXrefContactRepository.php b/Repository/CustomItemXrefContactRepository.php index 8297ed6c8..34d491e63 100644 --- a/Repository/CustomItemXrefContactRepository.php +++ b/Repository/CustomItemXrefContactRepository.php @@ -4,14 +4,13 @@ namespace MauticPlugin\CustomObjectsBundle\Repository; -use Mautic\CoreBundle\Entity\CommonRepository; use Mautic\LeadBundle\Entity\Lead; use MauticPlugin\CustomObjectsBundle\DTO\TableConfig; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefContact; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; -class CustomItemXrefContactRepository extends CommonRepository +class CustomItemXrefContactRepository extends CustomCommonRepository { /** * @return int[] diff --git a/Repository/CustomItemXrefCustomItemRepository.php b/Repository/CustomItemXrefCustomItemRepository.php index 079fc568d..bd058b92b 100644 --- a/Repository/CustomItemXrefCustomItemRepository.php +++ b/Repository/CustomItemXrefCustomItemRepository.php @@ -4,10 +4,9 @@ namespace MauticPlugin\CustomObjectsBundle\Repository; -use Mautic\CoreBundle\Entity\CommonRepository; use MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefCustomItem; -class CustomItemXrefCustomItemRepository extends CommonRepository +class CustomItemXrefCustomItemRepository extends CustomCommonRepository { public function deleteAllLinksForCustomItem(int $customItemId): void { diff --git a/Repository/CustomObjectRepository.php b/Repository/CustomObjectRepository.php index a9fa7b3a2..10592e27d 100644 --- a/Repository/CustomObjectRepository.php +++ b/Repository/CustomObjectRepository.php @@ -6,11 +6,10 @@ use Doctrine\ORM\Query\Expr\Orx; use Doctrine\ORM\QueryBuilder; -use Mautic\CoreBundle\Entity\CommonRepository; use Mautic\LeadBundle\Entity\LeadList; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; -class CustomObjectRepository extends CommonRepository +class CustomObjectRepository extends CustomCommonRepository { public function checkAliasExists(string $alias, ?int $id = null): bool { @@ -102,7 +101,7 @@ private function buildSegmentFilterForCustomObjectFields(CustomObject $customObj { $alias = 'cmo_'.$customObject->getId(); $aliasLength = mb_strlen($alias); - $like = "%;s:5:\"field\";s:${aliasLength}:\"{$alias}\";%"; + $like = "%;s:5:\"field\";s:{$aliasLength}:\"{$alias}\";%"; $filterExpression->add( $queryBuilder->expr()->like('l.filters', $queryBuilder->expr()->literal($like)) @@ -112,7 +111,7 @@ private function buildSegmentFilterForCustomObjectFields(CustomObject $customObj foreach ($customObject->getCustomFields() as $customField) { $alias = 'cmf_'.$customField->getId(); $aliasLength = mb_strlen($alias); - $like = "%;s:5:\"field\";s:${aliasLength}:\"{$alias}\";%"; + $like = "%;s:5:\"field\";s:{$aliasLength}:\"{$alias}\";%"; $filterExpression->add( $queryBuilder->expr()->like('l.filters', $queryBuilder->expr()->literal($like)) ); diff --git a/Repository/DbalQueryTrait.php b/Repository/DbalQueryTrait.php index 84ff8c72f..09a13e9d5 100644 --- a/Repository/DbalQueryTrait.php +++ b/Repository/DbalQueryTrait.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Query\QueryBuilder; +use Doctrine\DBAL\Result; trait DbalQueryTrait { @@ -14,11 +15,11 @@ trait DbalQueryTrait * * @throws \UnexpectedValueException */ - private function executeSelect(QueryBuilder $queryBuilder): Statement + private function executeSelect(QueryBuilder $queryBuilder): Result|Statement { $statement = $queryBuilder->execute(); - if ($statement instanceof Statement) { + if ($statement instanceof Result || $statement instanceof Statement) { return $statement; } diff --git a/Resources/views/CustomField/_detail_left_section.html.twig b/Resources/views/CustomField/_detail_left_section.html.twig new file mode 100644 index 000000000..9908463b5 --- /dev/null +++ b/Resources/views/CustomField/_detail_left_section.html.twig @@ -0,0 +1,25 @@ + +
    +
    + +
    +
    +
    +
    {{ item.type }}
    +
    +
    + {{ include('@MauticCore/Helper/publishstatus_badge.html.twig', { + entity: item + }) }} +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/Resources/views/CustomField/_detail_right_section.html.twig b/Resources/views/CustomField/_detail_right_section.html.twig new file mode 100644 index 000000000..8eedccc78 --- /dev/null +++ b/Resources/views/CustomField/_detail_right_section.html.twig @@ -0,0 +1,23 @@ + +
    + +
    +
    +
    + {{ 'mautic.webhook.webhook_url'|trans }} +
    +
    +
    +
    +
    + +
    + + + {{ include('@MauticCore/Helper/recentactivity.html.twig', { + logs: logs + }) }} +
    +
    + +
    \ No newline at end of file diff --git a/Resources/views/CustomField/detail.html.twig b/Resources/views/CustomField/detail.html.twig new file mode 100644 index 000000000..ec6a6e8bc --- /dev/null +++ b/Resources/views/CustomField/detail.html.twig @@ -0,0 +1,19 @@ +{% extends '@MauticCore/Default/content.html.twig.html.twig' %} + +{% block mauticContent %}customField{% endblock %} + +{% block headerTitle %} + {{ item.getName() }} +{% endblock %} + +{% block actions %} + {{ include('@MauticCore/Helper/page_actions.html.twig', { 'item': item }) }} +{% endblock %} + +{% block content %} + +
    + {{ include('@CustomObjects/CustomField/_detail_left_section.html.twig') }} + {{ include('@CustomObjects/CustomField/_detail_right_section.html.twig', {'logs': logs}) }} +
    +{% endblock %} \ No newline at end of file diff --git a/Resources/views/CustomField/form.html.twig b/Resources/views/CustomField/form.html.twig new file mode 100644 index 000000000..dd1d6ed5d --- /dev/null +++ b/Resources/views/CustomField/form.html.twig @@ -0,0 +1,97 @@ +{% set title = customField.id ? customField.label : customField.typeObject.name %} +{% set showProperties = form.options is defined or customField.typeObject.usePlaceholder() %} + +{% block content %} +
    +
    +

    {{ title }}

    +
    + + {{ form_start(form) }} +
    + + +
    +
    + +
    +
    + {{ form_row(form.label) }} +
    +
    + {{ form_row(form.showInCustomObjectDetailList) }} +
    +
    + +
    +
    + {{ form_row(form.alias) }} +
    +
    + {{ form_row(form.showInContactDetailList) }} +
    +
    + +
    +
    + {{ form_row(form.defaultValue) }} +
    +
    + {{ form_row(form.isUniqueIdentifier) }} +
    +
    + +
    + +
    +
    +
    + {{ form_row(form.required) }} +
    +
    +
    + + {% if showProperties %} +
    +
    + {% if form.options is defined %} +
    + {{ form_row(form.options) }} +
    + {% endif %} +
    +
    + {% if customField.typeObject.usePlaceholder %} +
    + {{ form_row(form.params.placeholder) }} +
    + {% endif %} +
    +
    + {% endif %} +
    +
    + + {{ form_rest(form) }} + {{ form_end(form) }} + +
    +{% endblock %} \ No newline at end of file diff --git a/Resources/views/CustomField/value.html.twig b/Resources/views/CustomField/value.html.twig new file mode 100644 index 000000000..b6193f571 --- /dev/null +++ b/Resources/views/CustomField/value.html.twig @@ -0,0 +1,15 @@ +{% set customFieldType = fieldValue.customField.type %} +{% set fieldTypes = ['select', 'multiselect'] %} + +{% if fieldValue.getValue() is instanceof('DateTimeInterface') %} + {% set date = 'date' == customFieldType ? dateToDate(fieldValue.getValue()) : dateToFull(fieldValue.getValue()) %} + {{ date }} +{% elseif customFieldType in fieldTypes %} +{# TODO: Transform to string #} +{# {{ '%s'|format(fieldValue.getCustomField().getTypeObject()|escape)|raw }}#} + {{ '%s'|format(fieldValue.getValue()|first|escape)|raw }} +{% elseif fieldValue.getValue() is iterable %} + {{ fieldValue.getValue()|join(', ') }} +{% else %} + {{ '%s'|format(fieldValue.getValue()|escape)|raw }} +{% endif %} \ No newline at end of file diff --git a/Resources/views/CustomItem/_detail_left_section.html.twig b/Resources/views/CustomItem/_detail_left_section.html.twig new file mode 100644 index 000000000..f511c0db6 --- /dev/null +++ b/Resources/views/CustomItem/_detail_left_section.html.twig @@ -0,0 +1,112 @@ + +
    +
    + +
    +
    +
    +
    + {% set nameSingular = item.getCustomObject().getNameSingular() %} + {{ '%s'|format(nameSingular|escape)|raw }} +
    +
    + {# TODO: Check if this block is needed #} +
    + {{ include('@MauticCore/Helper/publishstatus_badge.html.twig', { + entity: item + }) }} +
    +
    +
    + +
    +
    +
    + + + {{ include('@MauticCore/Helper/details.html.twig', { + entity: item + }) }} + {% for fieldValue in item.getCustomFieldValues() %} + + + + + {% endfor %} + +
    {{ '%s'|format(fieldValue.getCustomField().getName()|escape)|raw }} + {{ include('@CustomObjects/CustomField/value.html.twig', { + fieldValue: fieldValue + }) }} +
    +
    +
    +
    +
    + + +
    + + + + +
    +
    +
    +
    +
    +
    +
    + + {{ 'custom.item.links.in.time'|trans }} +
    +
    +
    + {{ include('@MauticCore/Helper/graph_dateselect.html.twig', { + dateRangeForm: dateRangeForm, + class: 'pull-right' + }) }} +
    +
    +
    + {{ include('@MauticCore/Helper/chart.html.twig', { + chartData: stats, + chartType: 'line', + chartHeight: 300 + }) }} +
    +
    +
    +
    +
    + {{ customContent('details.stats.graph.below', mauticTemplateVars is defined ? mauticTemplateVars : []) }} +
    + + + + + + +
    +
    + {{ contacts|raw }} +
    + {{ customContent('tabs.content', mauticTemplateVars|default({'mauticTemplate': '@CustomObjects/CustomItem/detail.html.twig', 'item': item}), '@CustomObjects/CustomItem/detail.html.twig') }} +
    + +
    \ No newline at end of file diff --git a/Resources/views/CustomItem/_detail_right_section.html.twig b/Resources/views/CustomItem/_detail_right_section.html.twig new file mode 100644 index 000000000..02d22b0ba --- /dev/null +++ b/Resources/views/CustomItem/_detail_right_section.html.twig @@ -0,0 +1,6 @@ + +
    + + {{ include('@MauticCore/Helper/recentactivity.html.twig', {'logs': logs}) }} +
    + \ No newline at end of file diff --git a/Resources/views/CustomItem/_list.html.twig b/Resources/views/CustomItem/_list.html.twig new file mode 100644 index 000000000..fd8544e24 --- /dev/null +++ b/Resources/views/CustomItem/_list.html.twig @@ -0,0 +1,96 @@ +{% set tableAlias = constant('MauticPlugin\\CustomObjectsBundle\\Entity\\CustomItem::TABLE_ALIAS') %} +{% set routeView = constant('MauticPlugin\\CustomObjectsBundle\\Provider\\CustomItemRouteProvider::ROUTE_VIEW') %} +{% set routeList = constant('MauticPlugin\\CustomObjectsBundle\\Provider\\CustomItemRouteProvider::ROUTE_LIST') %} + +{% set routerSelf = path(routeList, { + 'objectId': customObject.getId(), + 'filterEntityId': filterEntityId, + 'filterEntityType': filterEntityType, + 'lookup': lookup, + 'tmpl': 'list', +}) %} + +{% if items|length %} +
    + + + + {{- include('@MauticCore/Helper/tableheader.html.twig', { + 'checkall' : 'true', + 'target' : target, + 'langVar' : 'custom.item', + 'routeBase' : 'custom_item', + 'baseUrl' : routerSelf + }) -}} + {{- include('@MauticCore/Helper/tableheader.html.twig', { + 'sessionVar' : sessionVar, + 'orderBy' : tableAlias~'.name', + 'text' : 'mautic.core.name', + 'class' : 'col-custom_item_name', + 'baseUrl' : routerSelf, + 'target' : target + }) -}} + {{- include('@MauticCore/Helper/tableheader.html.twig', { + 'sessionVar' : sessionVar, + 'orderBy' : tableAlias~'.id', + 'text' : 'mautic.core.id', + 'default' : true, + 'baseUrl' : routerSelf, + 'target' : target + }) -}} + + {% if fieldData is not empty %} + {% for columnLabel in fieldData.getColumnLabels() %} + {{- include('@MauticCore/Helper/tableheader.html.twig', { 'text' : columnLabel }) -}} + {% endfor %} + {% endif %} + + + + {% for item in items %} + + + + + {% if fieldData is not empty %} + {% for fieldValue in fieldData.getFields(item.getId()) %} + + {% endfor %} + {% endif %} + + {% endfor %} + +
    + {{- include('@MauticCore/Helper/list_actions.html.twig', { 'item' : item }) -}} + +
    + {{ filterEntityId is empty ? include('@MauticCore/Helper/publishstatus_icon.html.twig', { 'item' : item, 'model' : 'custom.item' }) : '' }} + + {{ item.getName() }} + +
    +
    + {{ item.getId() }} + + {{- include('@CustomObjects/CustomField/value.html.twig', { 'fieldValue' : fieldValue }) -}} +
    +
    + +{% else %} + {{- include('@MauticCore/Helper/noresults.html.twig', { 'tip' : lookup ? 'custom.item.link.noresults.tip' : 'custom.object.noresults.tip' }) -}} +{% endif %} diff --git a/Resources/views/CustomItem/detail.html.twig b/Resources/views/CustomItem/detail.html.twig new file mode 100644 index 000000000..dc1910a28 --- /dev/null +++ b/Resources/views/CustomItem/detail.html.twig @@ -0,0 +1,27 @@ +{% extends '@MauticCore/Default/content.html.twig' %} + +{% block mauticContent %}customItem{% endblock %} + +{% block headerTitle %} + {{ item.getName() }} +{% endblock %} + +{% block actions %} + {{ include('@MauticCore/Helper/page_actions.html.twig', { 'item': item }) }} +{% endblock %} + +{% block publishStatus %} + {{- include('@MauticCore/Helper/publishstatus_badge.html.twig', {'entity' : item}) -}} +{% endblock %} + +{% block content %} +
    + {{ include('@CustomObjects/CustomItem/_detail_left_section.html.twig', { + 'entity': item, + 'dateRangeForm': dateRangeForm, + 'chartData': stats, + 'mauticTemplateVars': mauticTemplateVars is defined ? mauticTemplateVars : {} + }) }} + {{ include('@CustomObjects/CustomItem/_detail_right_section.html.twig', {'logs': logs}) }} +
    +{% endblock %} diff --git a/Resources/views/CustomItem/form.html.twig b/Resources/views/CustomItem/form.html.twig new file mode 100644 index 000000000..c23ff9e88 --- /dev/null +++ b/Resources/views/CustomItem/form.html.twig @@ -0,0 +1,56 @@ +{% extends '@MauticCore/Default/content.html.twig' %} + +{% block mauticContent %}customItem{% endblock %} + +{% block headerTitle %} + {% if entity.getId() is empty %} + {{ 'custom.item.new'|trans({'%object%' : customObject.getNameSingular()}) }} + {% else %} + {{ 'custom.item.edit'|trans({'%object%' : customObject.getNameSingular(), '%item%' : entity.getName()}) }} + {% endif %} +{% endblock %} + +{% block content %} + {% set typeRelationship = constant('MauticPlugin\\CustomObjectsBundle\\Entity\\CustomObject::TYPE_RELATIONSHIP') %} + {% set hideCategories = typeRelationship == customObject.getType() ? 'hide' : null %} + {% set fields = form.children %} + + {{ form_start(form) }} + +
    + +
    +
    +
    +
    + {%- if form.name is defined %}{{ form_row(form.name) }}{% endif %} + {{ form_row(form.custom_field_values) }} + {{ form_row(form.contact_id) }} +
    + {% if customObject.getRelationshipObject() is not empty and form.contact_id.vars.value is not empty %} +
    +
    +
    +

    + {{ 'custom.item.new'|trans({'%object%' : customObject.getRelationshipObject().getNameSingular()}) }} +

    +
    +
    + {{ form_row(fields, 'child_custom_field_values', template) }} +{# {{ formRowIfExists(fields, 'child_custom_field_values', template) }}#} +
    +
    +
    + {% endif %} +
    +
    +
    +
    +
    + {{ form_row(form.category) }} + {{ form_row(form.isPublished) }} +
    +
    +
    + {{ form_end(form) }} +{% endblock %} \ No newline at end of file diff --git a/Resources/views/CustomItem/list.html.twig b/Resources/views/CustomItem/list.html.twig new file mode 100644 index 000000000..88711f763 --- /dev/null +++ b/Resources/views/CustomItem/list.html.twig @@ -0,0 +1,37 @@ +{% set isIndex = tmpl == 'index' ? true : false %} +{% set tmpl = 'list' %} +{% set fieldData = fieldData ?? null %} +{% set target = '#'~namespace %} + +{% extends isIndex ? '@MauticCore/Default/content.html.twig' : '@MauticCore/Default/raw_output.html.twig' %} + +{% block mauticContent %}customItem{% endblock %} + +{% block headerTitle %} + {{ customObject.getName() }} +{% endblock %} + +{% block actions %} + {{ include('@MauticCore/Helper/page_actions.html.twig') }} +{% endblock %} + +{% block content %} +
    + {% if isIndex %} +
    + {{ include('@MauticCore/Helper/list_toolbar.html.twig', { + 'searchValue': searchValue, + 'action': currentRoute, + 'target': '#'~namespace, + 'overlayDisabled': lookup + }) }} + +
    + {{ include('@CustomObjects/CustomItem/_list.html.twig') }} +
    +
    + {% else %} + {{ include('@CustomObjects/CustomItem/_list.html.twig') }} + {% endif %} +
    +{% endblock %} \ No newline at end of file diff --git a/Resources/views/CustomObject/Form/Panel/_field.html.twig b/Resources/views/CustomObject/Form/Panel/_field.html.twig new file mode 100644 index 000000000..397e59bc0 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/_field.html.twig @@ -0,0 +1,47 @@ +{% set customFieldEntity = customField.vars.data %} +{#{% set customField.vars.index = customField.vars.name %}#} +{% set order = customField.vars.value.getOrder() %} +{#{{ dump(app.request.) }}#} +{# TODO !!!!!!!!!!!! Handle deleted objects#} +{#{% set requestCustomObject = app.request.post('custom_object') %}#} +{#{% set displayStyle = requestCustomObject['customFields'][order]['deleted'] is empty ? '' : 'style="display:none;"' %}#} +{% set displayStyle = '' %} +{% set panelId = panelId is empty ? customField.vars.value.getOrder()|number_format : panelId %} +{% set routeForm = constant('MauticPlugin\\CustomObjectsBundle\\Provider\\CustomFieldRouteProvider::ROUTE_FORM') %} + +
    +
    + + + + + +
    + +
    +
    +
    + {{ form_row(customField.defaultValue) }} +
    +
    +
    +
    + {{ form_rest(customField) }} +
    + +
    \ No newline at end of file diff --git a/Resources/views/CustomObject/Form/Panel/checkbox_group.html.twig b/Resources/views/CustomObject/Form/Panel/checkbox_group.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/checkbox_group.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/country.html.twig b/Resources/views/CustomObject/Form/Panel/country.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/country.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/date.html.twig b/Resources/views/CustomObject/Form/Panel/date.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/date.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/datetime.html.twig b/Resources/views/CustomObject/Form/Panel/datetime.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/datetime.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/email.html.twig b/Resources/views/CustomObject/Form/Panel/email.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/email.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/hidden.html.twig b/Resources/views/CustomObject/Form/Panel/hidden.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/hidden.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/html_area.html.twig b/Resources/views/CustomObject/Form/Panel/html_area.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/html_area.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/int.html.twig b/Resources/views/CustomObject/Form/Panel/int.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/int.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/multiselect.html.twig b/Resources/views/CustomObject/Form/Panel/multiselect.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/multiselect.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/phone.html.twig b/Resources/views/CustomObject/Form/Panel/phone.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/phone.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/radio_group.html.twig b/Resources/views/CustomObject/Form/Panel/radio_group.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/radio_group.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/select.html.twig b/Resources/views/CustomObject/Form/Panel/select.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/select.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/text.html.twig b/Resources/views/CustomObject/Form/Panel/text.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/text.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/Form/Panel/textarea.html.twig b/Resources/views/CustomObject/Form/Panel/textarea.html.twig new file mode 100644 index 000000000..8e26a3a45 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/textarea.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} \ No newline at end of file diff --git a/Resources/views/CustomObject/Form/Panel/url.html.twig b/Resources/views/CustomObject/Form/Panel/url.html.twig new file mode 100644 index 000000000..e226dbc02 --- /dev/null +++ b/Resources/views/CustomObject/Form/Panel/url.html.twig @@ -0,0 +1 @@ +{% extends '@CustomObjects/CustomObject/Form\\Panel\\_field.html.twig' %} diff --git a/Resources/views/CustomObject/_detail_left_section.html.twig b/Resources/views/CustomObject/_detail_left_section.html.twig new file mode 100644 index 000000000..8b1654671 --- /dev/null +++ b/Resources/views/CustomObject/_detail_left_section.html.twig @@ -0,0 +1,110 @@ + +
    +
    + +
    +
    +
    +
    +
    +
    + + + +
    +
    +
    + + + {{ include('@MauticCore/Helper/details.html.twig', {'entity': customObject}) }} + +
    +
    +
    +
    + +
    + + +
    + + + + +
    +
    +
    +
    +
    +
    +
    + + {{ 'custom.item.links.in.time'|trans }} +
    +
    +
    + {{ include('@MauticCore/Helper/graph_dateselect.html.twig', {'dateRangeForm': dateRangeForm, 'class': 'pull-right'}) }} +
    +
    +
    + {{ include('@MauticCore/Helper/chart.html.twig', {'chartData': chartData, 'chartType': 'line', 'chartHeight': 300}) }} +
    +
    +
    +
    +
    + {{- customContent('details.stats.graph.below', mauticTemplateVars|default({})) -}} + + + + +
    + +
    + + +
    +
      + {% for field in customObject.getCustomFields() %} +
    • +
      +
      +

      + {% set isRequired = field.isRequired() ? true : false %} + {% set requiredTitle = isRequired ? 'mautic.core.required' : 'mautic.core.not_required' %} + {% set requiredClass = isRequired ? 'check' : 'times' %} + + +

      +
      +
      +
      {{ field.getLabel() }}
      +
      +
      + {{ field.getTypeObject().getName() }} +
      +
      +
    • + {% endfor %} +
    +
    + +
    +
    \ No newline at end of file diff --git a/Resources/views/CustomObject/_detail_right_section.html.twig b/Resources/views/CustomObject/_detail_right_section.html.twig new file mode 100644 index 000000000..02d22b0ba --- /dev/null +++ b/Resources/views/CustomObject/_detail_right_section.html.twig @@ -0,0 +1,6 @@ + +
    + + {{ include('@MauticCore/Helper/recentactivity.html.twig', {'logs': logs}) }} +
    + \ No newline at end of file diff --git a/Resources/views/CustomObject/_form-fields.html.twig b/Resources/views/CustomObject/_form-fields.html.twig new file mode 100644 index 000000000..87f649c65 --- /dev/null +++ b/Resources/views/CustomObject/_form-fields.html.twig @@ -0,0 +1,19 @@ +{% set customFields = form.children['customFields'].getIterator().getArrayCopy() %} + +{% for customField in customFields %} + {% set customFieldEntity = customField.vars.data %} + + {% if customFieldEntity.getId() not in deletedFields %} + {{- include( + '@CustomObjects/CustomObject/Form\\Panel\\'~customFieldEntity.getType()~'.html.twig', + { + 'customField': customField, + 'customObject': customObject, + 'panelId': panelId ?? null, + + }) + -}} + {% endif %} +{% endfor %} + +{% do form.children['customFields'].setRendered() %} \ No newline at end of file diff --git a/Resources/views/CustomObject/_list.html.twig b/Resources/views/CustomObject/_list.html.twig new file mode 100644 index 000000000..1d6766b03 --- /dev/null +++ b/Resources/views/CustomObject/_list.html.twig @@ -0,0 +1,74 @@ +{% set tableAlias = constant('MauticPlugin\\CustomObjectsBundle\\Entity\\CustomObject::TABLE_ALIAS') %} +{% set routeView = constant('MauticPlugin\\CustomObjectsBundle\\Provider\\CustomObjectRouteProvider::ROUTE_VIEW') %} +{% set routeList = constant('MauticPlugin\\CustomObjectsBundle\\Provider\\CustomObjectRouteProvider::ROUTE_LIST') %} + +{% if items|length > 0 %} +
    + + + + {{ include('@MauticCore/Helper/tableheader.html.twig', { + 'checkall': 'true', + 'target': '#custom-objects-table', + 'langVar': 'custom.object', + 'routeBase': 'custom_object', + 'routeBase': 'form' + }) }} + + {{ include('@MauticCore/Helper/tableheader.html.twig', { + 'sessionVar': sessionVar, + 'orderBy': tableAlias~'.namePlural', + 'text': 'mautic.core.name', + 'class': 'col-custom_object_-name' + }) }} + + {{ include('@MauticCore/Helper/tableheader.html.twig', { + 'sessionVar': sessionVar, + 'orderBy': tableAlias~'.id', + 'text': 'mautic.core.id', + 'default': true + }) }} + + + + {% for item in items %} + + + + + + {% endfor %} + +
    + {{- include('@MauticCore/Helper/list_actions.html.twig', { 'item': item }) -}} + +
    + {{- include('@MauticCore/Helper/publishstatus_icon.html.twig', + {'item' : item, 'model' : 'custom.object'}) -}} + + {{ item.name }} + +{# #} +{# {{ item.getName() }}#} +{# #} +
    + {% if item.description %} +
    + {{ item.description|purify }} +
    + {% endif %} +
    {{ item.id }}
    +
    + +{% else %} + {{ include('@MauticCore/Helper/noresults.html.twig', {'tip': 'custom.object.noresults.tip'}) }} +{% endif %} diff --git a/Resources/views/CustomObject/detail.html.twig b/Resources/views/CustomObject/detail.html.twig new file mode 100644 index 000000000..80ebb9534 --- /dev/null +++ b/Resources/views/CustomObject/detail.html.twig @@ -0,0 +1,27 @@ +{% extends '@MauticCore/Default/content.html.twig' %} + +{% block mauticContent %}customObject{% endblock %} + +{% block headerTitle %} + {{ customObject.getNameSingular() }} +{% endblock %} + +{% block actions %} + {{ include('@MauticCore/Helper/page_actions.html.twig', { 'item': customObject}) }} +{% endblock %} + +{% block publishStatus %} + {{- include('@MauticCore/Helper/publishstatus_badge.html.twig', {'entity' : customObject}) -}} +{% endblock %} + +{% block content %} +
    + {{ include('@CustomObjects/CustomObject/_detail_left_section.html.twig', { + 'entity': customObject, + 'dateRangeForm': dateRangeForm, + 'chartData': stats, + 'mauticTemplateVars': mauticTemplateVars is defined ? mauticTemplateVars : {} + }) }} + {{ include('@CustomObjects/CustomObject/_detail_right_section.html.twig', {'logs': logs}) }} +
    +{% endblock %} \ No newline at end of file diff --git a/Resources/views/CustomObject/form.html.twig b/Resources/views/CustomObject/form.html.twig new file mode 100644 index 000000000..d630e8246 --- /dev/null +++ b/Resources/views/CustomObject/form.html.twig @@ -0,0 +1,98 @@ +{% extends '@MauticCore/Default/content.html.twig' %} + +{% block mauticContent %}customObject{% endblock %} + +{% block headerTitle %} + {% if customObject.getId() %} + {{ 'custom.object.edit'|trans({'%name%' : customObject.getName()|trans}) }} + {% else %} + {% trans %}custom.object.new{% endtrans %} + {% endif %} +{% endblock %} + +{% block content %} + {{ form_start(form) }} +
    + +
    +
    +
    + + + +
    +
    +
    +
    + {{ form_row(form.nameSingular) }} + {{ form_row(form.namePlural) }} +
    +
    + {{ form_row(form.alias) }} +
    +
    +
    +
    + {{ form_row(form.description) }} +
    +
    +
    + +
    + {{- include('@MauticForm/Builder/_style.html.twig') -}} +
    +
    +
    + +
    +
    +
    + {{- include('@CustomObjects/CustomObject/_form-fields.html.twig') -}} +
    + {% if 0 == customFields|length %} +
    +

    {{ 'mautic.form.form.addfield'|trans }}

    +
    + {% endif %} +
    +
    +
    +
    +
    +
    +
    +
    + {{ form_row(form.type) }} + {{ form_row(form.masterObject) }} + {{ form_row(form.category) }} + {{ form_row(form.isPublished) }} +
    +
    +
    + {{ form_end(form) }} +{% endblock %} + +{% block modal %} + {{ include('@MauticCore/Helper/modal.html.twig', { + 'id': 'objectFieldModal', + 'header': false, + 'footerButtons': true, + }) }} +{% endblock %} \ No newline at end of file diff --git a/Resources/views/CustomObject/list.html.twig b/Resources/views/CustomObject/list.html.twig new file mode 100644 index 000000000..6cb28b6ba --- /dev/null +++ b/Resources/views/CustomObject/list.html.twig @@ -0,0 +1,27 @@ +{% set isIndex = tmpl == 'index' ? true : false %} +{% set tmpl = 'list' %} + +{% extends isIndex ? '@MauticCore/Default/content.html.twig' : '@MauticCore/Default/raw_output.html.twig' %} + +{% block mauticContent %}customObject{% endblock %} + +{% block headerTitle %} + {{ 'custom.object.title'|trans }} +{% endblock %} + +{% block actions %} + {{ include('@MauticCore/Helper/page_actions.html.twig') }} +{% endblock %} + +{% block content %} + {% if isIndex %} +
    + {{ include('@MauticCore/Helper/list_toolbar.html.twig') }} +
    ! + {{ include('@CustomObjects/CustomObject/_list.html.twig') }} +
    +
    + {% else %} + {{ include('@CustomObjects/CustomObject/_list.html.twig') }} + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/Views/FormTheme/FieldValueCondition/campaign_condition_field_value_widget.html.php b/Resources/views/FormTheme/FieldValueCondition/campaign_condition_field_value_widget.html.twig similarity index 56% rename from Views/FormTheme/FieldValueCondition/campaign_condition_field_value_widget.html.php rename to Resources/views/FormTheme/FieldValueCondition/campaign_condition_field_value_widget.html.twig index 3c1b71b88..35c606a32 100644 --- a/Views/FormTheme/FieldValueCondition/campaign_condition_field_value_widget.html.php +++ b/Resources/views/FormTheme/FieldValueCondition/campaign_condition_field_value_widget.html.twig @@ -3,13 +3,13 @@ ?>
    - row($form['field']); ?> + {{ form_row(field) }}
    - row($form['operator']); ?> + {{ form_row(operator) }}
    - row($form['value']); ?> + {{ form_row(value) }}
    diff --git a/Resources/views/SubscribedEvents/Tab/content.html.twig b/Resources/views/SubscribedEvents/Tab/content.html.twig new file mode 100644 index 000000000..d5f99f144 --- /dev/null +++ b/Resources/views/SubscribedEvents/Tab/content.html.twig @@ -0,0 +1,49 @@ +
    +
    +
    + {{ include('@MauticCore/Helper/search.html.twig', { + 'searchValue': searchValue, + 'action': searchRoute, + 'searchId': searchId, + 'target': '#'~namespace, + 'searchHelp': '' + }) }} +
    + +
    +
    + Loading... +
    +
    + + + + diff --git a/Resources/views/SubscribedEvents/Tab/link.html.twig b/Resources/views/SubscribedEvents/Tab/link.html.twig new file mode 100644 index 000000000..304c26ac0 --- /dev/null +++ b/Resources/views/SubscribedEvents/Tab/link.html.twig @@ -0,0 +1,11 @@ +
  • + + {% if count is defined %} + + {{ count }} + + {% endif %} + + {{ title|trans }} + +
  • \ No newline at end of file diff --git a/Resources/views/SubscribedEvents/Tab/modal.html.twig b/Resources/views/SubscribedEvents/Tab/modal.html.twig new file mode 100644 index 000000000..70c836855 --- /dev/null +++ b/Resources/views/SubscribedEvents/Tab/modal.html.twig @@ -0,0 +1,6 @@ +{% block modal %} + {{ include('@MauticCore/Helper/modal.html.twig', { + 'id': 'customItemLookupModal', + 'size': 'xl' + }) }} +{% endblock %} \ No newline at end of file diff --git a/Resources/views/SubscribedEvents/Timeline/link.html.twig b/Resources/views/SubscribedEvents/Timeline/link.html.twig new file mode 100644 index 000000000..36efb8b5b --- /dev/null +++ b/Resources/views/SubscribedEvents/Timeline/link.html.twig @@ -0,0 +1,12 @@ +{% set link = event.extra %} + +
    + {% if link.user_id is not empty %} +
    {{ 'mautic.core.createdby'|trans }}
    +
    + + {{ link.user_name }} + +
    + {% endif %} +
    diff --git a/Security/Permissions/CustomObjectPermissions.php b/Security/Permissions/CustomObjectPermissions.php index 522d49f91..9c4b1f50e 100644 --- a/Security/Permissions/CustomObjectPermissions.php +++ b/Security/Permissions/CustomObjectPermissions.php @@ -10,27 +10,12 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel; use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomObjectPermissions extends AbstractPermissions { public const NAME = 'custom_objects'; - /** - * @var CustomObjectModel - */ - private $customObjectModel; - - /** - * @var ConfigProvider - */ - private $configProvider; - - /** - * @var TranslatorInterface - */ - private $translator; - /** * Cached custom objects. * @@ -40,15 +25,11 @@ class CustomObjectPermissions extends AbstractPermissions public function __construct( CoreParametersHelper $coreParametersHelper, - CustomObjectModel $customObjectModel, - ConfigProvider $configProvider, - TranslatorInterface $translator + private CustomObjectModel $customObjectModel, + private ConfigProvider $configProvider, + private TranslatorInterface $translator ) { parent::__construct($coreParametersHelper->all()); - - $this->customObjectModel = $customObjectModel; - $this->configProvider = $configProvider; - $this->translator = $translator; } /** diff --git a/Segment/Query/Filter/CustomFieldFilterQueryBuilder.php b/Segment/Query/Filter/CustomFieldFilterQueryBuilder.php index bc38e0adb..54cdbf167 100644 --- a/Segment/Query/Filter/CustomFieldFilterQueryBuilder.php +++ b/Segment/Query/Filter/CustomFieldFilterQueryBuilder.php @@ -14,23 +14,16 @@ class CustomFieldFilterQueryBuilder extends BaseFilterQueryBuilder { - /** - * @var QueryFilterHelper - */ - private $filterHelper; - public function __construct( RandomParameterName $randomParameterNameService, EventDispatcherInterface $dispatcher, - QueryFilterHelper $filterHelper + private QueryFilterHelper $filterHelper ) { parent::__construct($randomParameterNameService, $dispatcher); - - $this->filterHelper = $filterHelper; } /** {@inheritdoc} */ - public static function getServiceId() + public static function getServiceId(): string { return 'mautic.lead.query.builder.custom_field.value'; } @@ -45,10 +38,7 @@ public function applyQuery(SegmentQueryBuilder $queryBuilder, ContactSegmentFilt $tableAlias = 'cfwq_'.(int) $filter->getField(); - $unionQueryContainer = $this->filterHelper->createValueQuery( - $tableAlias, - $filter - ); + $unionQueryContainer = $this->filterHelper->createValueQuery($tableAlias, $filter, true); foreach ($unionQueryContainer as $segmentQueryBuilder) { $segmentQueryBuilder->andWhere( @@ -56,23 +46,16 @@ public function applyQuery(SegmentQueryBuilder $queryBuilder, ContactSegmentFilt ); } - switch ($filterOperator) { - case 'empty': - case 'neq': - case 'notLike': - case '!multiselect': - $queryBuilder->addLogic( - $queryBuilder->expr()->notExists($unionQueryContainer->getSQL()), - $filter->getGlue() - ); - - break; - default: - $queryBuilder->addLogic( - $queryBuilder->expr()->exists($unionQueryContainer->getSQL()), - $filter->getGlue() - ); - } + match ($filterOperator) { + 'empty', 'neq', 'notLike', '!multiselect', '!between', 'notBetween' => $queryBuilder->addLogic( + $queryBuilder->expr()->notExists($unionQueryContainer->getSQL()), + $filter->getGlue() + ), + default => $queryBuilder->addLogic( + $queryBuilder->expr()->exists($unionQueryContainer->getSQL()), + $filter->getGlue() + ), + }; $queryBuilder->setParameters($unionQueryContainer->getParameters(), $unionQueryContainer->getParameterTypes()); diff --git a/Segment/Query/Filter/CustomItemNameFilterQueryBuilder.php b/Segment/Query/Filter/CustomItemNameFilterQueryBuilder.php index 21d220b7e..d8c184d1f 100644 --- a/Segment/Query/Filter/CustomItemNameFilterQueryBuilder.php +++ b/Segment/Query/Filter/CustomItemNameFilterQueryBuilder.php @@ -17,18 +17,12 @@ class CustomItemNameFilterQueryBuilder extends BaseFilterQueryBuilder { use QueryBuilderManipulatorTrait; - /** - * @var QueryFilterHelper - */ - private $filterHelper; - public function __construct( RandomParameterName $randomParameterNameService, - QueryFilterHelper $filterHelper, + private QueryFilterHelper $filterHelper, EventDispatcherInterface $dispatcher ) { parent::__construct($randomParameterNameService, $dispatcher); - $this->filterHelper = $filterHelper; } public static function getServiceId(): string @@ -64,16 +58,10 @@ public function applyQuery(QueryBuilder $queryBuilder, ContactSegmentFilter $fil $filterQueryBuilder->select($tableAlias.'_contact.contact_id as lead_id'); $filterQueryBuilder->andWhere($leadsTableAlias.'.id = '.$tableAlias.'_contact.contact_id'); - switch ($filter->getOperator()) { - case 'empty': - case 'neq': - case 'notLike': - $queryBuilder->addLogic($queryBuilder->expr()->notExists($filterQueryBuilder->getSQL()), $filter->getGlue()); - - break; - default: - $queryBuilder->addLogic($queryBuilder->expr()->exists($filterQueryBuilder->getSQL()), $filter->getGlue()); - } + match ($filter->getOperator()) { + 'empty', 'neq', 'notLike' => $queryBuilder->addLogic($queryBuilder->expr()->notExists($filterQueryBuilder->getSQL()), $filter->getGlue()), + default => $queryBuilder->addLogic($queryBuilder->expr()->exists($filterQueryBuilder->getSQL()), $filter->getGlue()), + }; $this->copyParams($filterQueryBuilder, $queryBuilder); diff --git a/Segment/Query/Filter/CustomObjectMergedFilterQueryBuilder.php b/Segment/Query/Filter/CustomObjectMergedFilterQueryBuilder.php new file mode 100644 index 000000000..04161419e --- /dev/null +++ b/Segment/Query/Filter/CustomObjectMergedFilterQueryBuilder.php @@ -0,0 +1,38 @@ +getTableAlias(MAUTIC_TABLE_PREFIX.'leads'); + $subQuery = $this->queryFilterHelper->createMergeFilterQuery($filter, $leadsTableAlias); + $queryBuilder->addLogic($queryBuilder->expr()->exists($subQuery->getSQL()), $filter->getGlue()); + $queryBuilder->setParameters($subQuery->getParameters(), $subQuery->getParameterTypes()); + + return $queryBuilder; + } +} diff --git a/Segment/Query/Filter/QueryFilterFactory.php b/Segment/Query/Filter/QueryFilterFactory.php index 4907b3aa4..084c42854 100644 --- a/Segment/Query/Filter/QueryFilterFactory.php +++ b/Segment/Query/Filter/QueryFilterFactory.php @@ -13,22 +13,10 @@ class QueryFilterFactory { - /** - * @var ContactSegmentFilterFactory - */ - private $contactSegmentFilterFactory; - - /** - * @var QueryFilterHelper - */ - private $queryFilterHelper; - public function __construct( - ContactSegmentFilterFactory $filterFactory, - QueryFilterHelper $queryFilterHelper + private ContactSegmentFilterFactory $contactSegmentFilterFactory, + private QueryFilterHelper $queryFilterHelper ) { - $this->contactSegmentFilterFactory = $filterFactory; - $this->queryFilterHelper = $queryFilterHelper; } /** diff --git a/Segment/Query/UnionQueryContainer.php b/Segment/Query/UnionQueryContainer.php index 19f833ddc..55db816a5 100644 --- a/Segment/Query/UnionQueryContainer.php +++ b/Segment/Query/UnionQueryContainer.php @@ -17,29 +17,24 @@ class UnionQueryContainer implements \Iterator /** * @var SegmentQueryBuilder[] */ - private $queries = []; + private array $queries = []; /** - * @var array + * @var mixed[] */ - private $parameters = []; + private array $parameters = []; /** - * @var array + * @var mixed[] */ - private $parameterTypes = []; + private array $parameterTypes = []; - /** - * @var int - */ - private $position = 0; + private int $position = 0; /** * Whether parameters needs to be rebuild. - * - * @var bool */ - private $needsRebuild = false; + private bool $needsRebuild = false; public function add(SegmentQueryBuilder $queryBuilder): void { diff --git a/Serializer/ApiNormalizer.php b/Serializer/ApiNormalizer.php index 25ced4e37..c9f2b991f 100644 --- a/Serializer/ApiNormalizer.php +++ b/Serializer/ApiNormalizer.php @@ -20,16 +20,6 @@ final class ApiNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface { - /** - * @var CustomFieldTypeProvider - */ - private $customFieldTypeProvider; - - /** - * @var CustomItemModel - */ - private $customItemModel; - /** * @var NormalizerInterface */ @@ -40,22 +30,19 @@ final class ApiNormalizer implements NormalizerInterface, DenormalizerInterface, */ private $iriConverter; - /** - * @var EntityManager - */ - private $em; - - public function __construct(NormalizerInterface $decorated, CustomFieldTypeProvider $customFieldTypeProvider, CustomItemModel $customItemModel, IriConverterInterface $iriConverter, EntityManager $em) + public function __construct( + NormalizerInterface $decorated, + private CustomFieldTypeProvider $customFieldTypeProvider, + private CustomItemModel $customItemModel, + IriConverterInterface $iriConverter, + private EntityManager $em) { if (!$decorated instanceof DenormalizerInterface) { throw new InvalidArgumentException(sprintf('The decorated normalizer must implement the %s.', DenormalizerInterface::class)); } $this->decorated = $decorated; - $this->customFieldTypeProvider = $customFieldTypeProvider; - $this->customItemModel = $customItemModel; $this->iriConverter = $iriConverter; - $this->em = $em; } public function supportsNormalization($data, $format = null) @@ -98,7 +85,7 @@ public function denormalize($data, $class, $format = null, array $context = []) return $this->decorated->denormalize($data, $class, $format, $context); } - public function setSerializer(SerializerInterface $serializer) + public function setSerializer(SerializerInterface $serializer): void { if ($this->decorated instanceof SerializerAwareInterface) { $this->decorated->setSerializer($serializer); diff --git a/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php b/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php index d15f1e75a..85a994a01 100644 --- a/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php +++ b/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php @@ -6,7 +6,6 @@ use Mautic\CoreBundle\Test\MauticMysqlTestCase; use Mautic\UserBundle\Entity\Permission; use Mautic\UserBundle\Entity\User; -use ReflectionClass; use Symfony\Component\HttpFoundation\Response; abstract class AbstractApiPlatformFunctionalTest extends MauticMysqlTestCase @@ -58,7 +57,7 @@ protected function setPermission(User $user, string $permission, array $permissi $this->em->flush(); // reset in-memory permission cache - $property = (new ReflectionClass(CorePermissions::class))->getProperty('grantedPermissions'); + $property = (new \ReflectionClass(CorePermissions::class))->getProperty('grantedPermissions'); $property->setAccessible(true); $property->setValue(self::$container->get('mautic.security'), []); } @@ -78,6 +77,14 @@ protected function updateEntity(string $createdId, array $payload): Response return $this->requestEntity('PUT', $createdId, $payload); } + /** + * @param array $payload + */ + protected function patchEntity(string $createdId, array $payload): Response + { + return $this->requestEntity('PATCH', $createdId, $payload); + } + protected function deleteEntity(string $createdId): Response { return $this->requestEntity('DELETE', $createdId); @@ -85,7 +92,7 @@ protected function deleteEntity(string $createdId): Response protected function requestEntity(string $method, string $path, $payload = null): Response { - $server = ['CONTENT_TYPE' => 'application/ld+json', 'HTTP_ACCEPT' => 'application/ld+json']; + $server = ['CONTENT_TYPE' => 'PATCH' == $method ? 'application/merge-patch+json' : 'application/ld+json', 'HTTP_ACCEPT' => 'application/ld+json']; $this->client->request($method, $path, [], [], $server, $payload ? json_encode($payload) : null); return $this->client->getResponse(); diff --git a/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php b/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php index 6179a2543..5d6a8f24b 100644 --- a/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php +++ b/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php @@ -85,7 +85,7 @@ private function getCreatePayload(string $customObject): array 'string1', 'string2', ], - 'isPublished' => false, + 'isPublished' => false, 'isUniqueIdentifier' => false, ]; } @@ -102,7 +102,7 @@ private function getEditPayload(): array 'string1', 'string2', ], - 'isPublished' => true, + 'isPublished' => true, 'isUniqueIdentifier' => true, ]; } @@ -116,41 +116,41 @@ private function getCRUDProvider(): array { return [ 'all_ok' => [ - ['viewown', 'viewother', 'editown', 'editother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'New Custom Field', - Response::HTTP_OK, - 'Edited Custom Field', - Response::HTTP_NO_CONTENT, - ], + ['viewown', 'viewother', 'editown', 'editother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], + Response::HTTP_CREATED, + Response::HTTP_OK, + 'New Custom Field', + Response::HTTP_OK, + 'Edited Custom Field', + Response::HTTP_NO_CONTENT, + ], 'no_delete' => [ - ['viewown', 'viewother', 'editown', 'editother', 'create', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'New Custom Field', - Response::HTTP_OK, - 'Edited Custom Field', - Response::HTTP_FORBIDDEN, - ], + ['viewown', 'viewother', 'editown', 'editother', 'create', 'publishown', 'publishother'], + Response::HTTP_CREATED, + Response::HTTP_OK, + 'New Custom Field', + Response::HTTP_OK, + 'Edited Custom Field', + Response::HTTP_FORBIDDEN, + ], 'no_update' => [ - ['viewown', 'viewother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'New Custom Field', - Response::HTTP_FORBIDDEN, - null, - Response::HTTP_NO_CONTENT, - ], + ['viewown', 'viewother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], + Response::HTTP_CREATED, + Response::HTTP_OK, + 'New Custom Field', + Response::HTTP_FORBIDDEN, + null, + Response::HTTP_NO_CONTENT, + ], 'no_create' => [ - ['viewown', 'viewother', 'editown', 'editother', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_FORBIDDEN, - '', - null, - '', - null, - '', - ], + ['viewown', 'viewother', 'editown', 'editother', 'deleteown', 'deleteother', 'publishown', 'publishother'], + Response::HTTP_FORBIDDEN, + '', + null, + '', + null, + '', + ], ]; } diff --git a/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php b/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php index 81d331717..daea1f0b4 100644 --- a/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php +++ b/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php @@ -9,7 +9,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Helper\CsvHelper; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; final class CustomFieldOptionFunctionalTest extends AbstractApiPlatformFunctionalTest { @@ -126,41 +126,41 @@ private function getCRUDProvider(): array { return [ 'all_ok' => [ - ['viewown', 'viewother', 'editown', 'editother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'New Custom Field Option', - Response::HTTP_OK, - 'Edited Custom Field Option', - Response::HTTP_NO_CONTENT, - ], + ['viewown', 'viewother', 'editown', 'editother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], + Response::HTTP_CREATED, + Response::HTTP_OK, + 'New Custom Field Option', + Response::HTTP_OK, + 'Edited Custom Field Option', + Response::HTTP_NO_CONTENT, + ], 'no_delete' => [ - ['viewown', 'viewother', 'editown', 'editother', 'create', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'New Custom Field Option', - Response::HTTP_OK, - 'Edited Custom Field Option', - Response::HTTP_FORBIDDEN, - ], + ['viewown', 'viewother', 'editown', 'editother', 'create', 'publishown', 'publishother'], + Response::HTTP_CREATED, + Response::HTTP_OK, + 'New Custom Field Option', + Response::HTTP_OK, + 'Edited Custom Field Option', + Response::HTTP_FORBIDDEN, + ], 'no_update' => [ - ['viewown', 'viewother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'New Custom Field Option', - Response::HTTP_FORBIDDEN, - null, - Response::HTTP_NO_CONTENT, - ], + ['viewown', 'viewother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], + Response::HTTP_CREATED, + Response::HTTP_OK, + 'New Custom Field Option', + Response::HTTP_FORBIDDEN, + null, + Response::HTTP_NO_CONTENT, + ], 'no_create' => [ - ['viewown', 'viewother', 'editown', 'editother', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_FORBIDDEN, - '', - null, - '', - null, - '', - ], + ['viewown', 'viewother', 'editown', 'editother', 'deleteown', 'deleteother', 'publishown', 'publishother'], + Response::HTTP_FORBIDDEN, + '', + null, + '', + null, + '', + ], ]; } } diff --git a/Tests/Functional/ApiPlatform/CustomItemFunctionalTest.php b/Tests/Functional/ApiPlatform/CustomItemFunctionalTest.php index 68066f97f..9c04b5e54 100644 --- a/Tests/Functional/ApiPlatform/CustomItemFunctionalTest.php +++ b/Tests/Functional/ApiPlatform/CustomItemFunctionalTest.php @@ -7,157 +7,239 @@ use Mautic\LeadBundle\Provider\FilterOperatorProviderInterface; use MauticPlugin\CustomObjectsBundle\CustomFieldType\TextType; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; +use MauticPlugin\CustomObjectsBundle\Entity\CustomFieldValueText; +use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; +use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; final class CustomItemFunctionalTest extends AbstractApiPlatformFunctionalTest { - public function testCustomItemCRUD(): void + private CustomItemModel $customItemModel; + + public function setUp(): void + { + $this->configParams['custom_objects_enabled'] = true; + + parent::setUp(); + + $customItemModel = $this->getContainer()->get('mautic.custom.model.item'); + \assert($customItemModel instanceof CustomItemModel); + + $this->customItemModel = $customItemModel; + } + + /** + * @dataProvider getCustomItemsDataProvider + * + * @param array $permissions + */ + public function testGetCustomItem(array $permissions, int $expectedResponse): void + { + $customItem = $this->createCustomItem($permissions); + $response = $this->retrieveEntity('/api/v2/custom_items/'.$customItem->getId()); + $json = json_decode($response->getContent(), true); + + self::assertEquals($expectedResponse, $response->getStatusCode()); + + if (Response::HTTP_FORBIDDEN == $expectedResponse) { + $this->assertAccessForbiddenContent($json); + + return; + } + + $this->assertSuccessContent($json, $customItem); + } + + /** + * @return iterable + */ + public function getCustomItemsDataProvider(): iterable + { + yield [['viewother'], Response::HTTP_OK]; + + yield [['editother'], Response::HTTP_OK]; + + yield [['deleteother'], Response::HTTP_OK]; + + yield [['publishother'], Response::HTTP_OK]; + + yield [[], Response::HTTP_FORBIDDEN]; + + yield [['viewown', 'editown', 'create', 'deleteown', 'publishown'], Response::HTTP_FORBIDDEN]; + } + + /** + * @dataProvider postCustomItemsDataProvider + * + * @param array $permissions + */ + public function testPostCustomItem(array $permissions, int $expectedResponse): void { $customObject = $this->createCustomObject(); $category = $this->createCategory(); $customField = $this->createCustomField($customObject); + $user = $this->getUser(); + + $this->setPermission($user, 'custom_objects:'.$customObject->getId(), $permissions); + + $response = $this->createEntity('custom_items', [ + 'name' => 'Custom Item', + 'customObject' => '/api/v2/custom_objects/'.$customObject->getId(), + 'language' => 'en', + 'category' => '/api/v2/categories/'.$category->getId(), + 'fieldValues' => [ + [ + 'id' => '/api/v2/custom_fields/'.$customField->getId(), + 'value' => 'value', + ], + ], + ]); + $json = json_decode($response->getContent(), true); + + self::assertEquals($expectedResponse, $response->getStatusCode()); + + if (Response::HTTP_FORBIDDEN == $expectedResponse) { + $this->assertAccessForbiddenContent($json); - foreach ($this->getCRUDProvider() as $parameters) { - $this->runTestCustomItemCRUD(...array_merge([$customObject, $category, $customField], $parameters)); + return; } + + $this->em->clear(); + $customItem = $this->em->getRepository(CustomItem::class)->find($json['id']); + $this->customItemModel->populateCustomFields($customItem); + $this->assertSuccessContent($json, $customItem); } /** - * @throws \Doctrine\ORM\ORMException + * @return iterable */ - private function runTestCustomItemCRUD( - CustomObject $customObject, - Category $category, - CustomField $customField, - array $permissions, - string $httpCreated, - string $httpRetrieved, - ?string $retrievedAlias, - ?string $retrievedVariable, - string $httpUpdated, - ?string $updatedAlias, - ?string $updatedVariable, - string $httpDeleted - ): void { - // USER - $user = $this->getUser(); - // PERMISSION - $this->setPermission($user, 'custom_objects:'.$customObject->getId(), $permissions); - // CREATE - $payloadCreate = $this->getCreatePayload($customObject, $category, $customField); - $clientCreateResponse = $this->createEntity('custom_items', $payloadCreate); - $this->assertEquals($httpCreated, $clientCreateResponse->getStatusCode()); - if (Response::HTTP_FORBIDDEN === $clientCreateResponse->getStatusCode()) { + public function postCustomItemsDataProvider(): iterable + { + yield [['create'], Response::HTTP_CREATED]; + + yield [[], Response::HTTP_FORBIDDEN]; + + yield [['viewown', 'viewother', 'editown', 'editother', 'deleteown', 'deleteother', 'publishown', 'publishother'], Response::HTTP_FORBIDDEN]; + } + + /** + * @dataProvider putCustomItemsDataProvider + * + * @param array $permissions + */ + public function testPutCustomItem(array $permissions, int $expectedResponse): void + { + $customItem = $this->createCustomItem($permissions); + $response = $this->updateEntity('/api/v2/custom_items/'.$customItem->getId(), [ + 'name' => 'Custom Item Edited', + 'fieldValues' => [ + [ + 'id' => '/api/v2/custom_fields/'.$customItem->getCustomObject()->getCustomFields()->first()->getId(), + 'value' => 'test3', + ], + ], + ]); + $json = json_decode($response->getContent(), true); + + self::assertEquals($expectedResponse, $response->getStatusCode()); + + if (Response::HTTP_FORBIDDEN == $expectedResponse) { + $this->assertAccessForbiddenContent($json); + return; } - // GET ID OF ENTITY - $createdId = json_decode($clientCreateResponse->getContent())->{'@id'}; - // RETRIEVE - $clientRetrieveResponse = $this->retrieveEntity($createdId); - $this->assertEquals($httpRetrieved, $clientRetrieveResponse->getStatusCode()); - if ($retrievedAlias) { - $this->assertEquals($retrievedAlias, json_decode($clientRetrieveResponse->getContent())->name); - $this->assertEquals($retrievedVariable, json_decode($clientRetrieveResponse->getContent(), true)['fieldValues'][0]['value']); - } - // UPDATE - $payloadUpdate = $this->getEditPayload($customField); - $clientUpdateResponse = $this->updateEntity($createdId, $payloadUpdate); - $this->assertEquals($httpUpdated, $clientUpdateResponse->getStatusCode()); - if ($updatedAlias) { - $this->assertEquals($updatedAlias, json_decode($clientUpdateResponse->getContent())->name); - $this->assertEquals($updatedVariable, json_decode($clientUpdateResponse->getContent(), true)['fieldValues'][0]['value']); - } - // DELETE - $clientDeleteResponse = $this->deleteEntity($createdId); - $this->assertEquals($httpDeleted, $clientDeleteResponse->getStatusCode()); + + $this->em->clear(); + $customItem = $this->em->getRepository(CustomItem::class)->find($json['id']); + $this->customItemModel->populateCustomFields($customItem); + $this->assertSuccessContent($json, $customItem); } - private function getCreatePayload(CustomObject $customObject, Category $category, CustomField $customField): array + /** + * @return iterable + */ + public function putCustomItemsDataProvider(): iterable { - return - [ - 'name' => 'Custom Item Created', - 'customObject' => '/api/v2/custom_objects/'.$customObject->getId(), - 'language' => 'en', - 'category' => '/api/v2/categories/'.$category->getId(), - 'fieldValues' => [ - [ - 'id' => '/api/v2/custom_fields/'.$customField->getId(), - 'value' => 'test', - ], - ], - ]; + yield [['editother'], Response::HTTP_OK]; + + yield [['deleteother'], Response::HTTP_OK]; + + yield [[], Response::HTTP_FORBIDDEN]; + + yield [['viewown', 'viewother', 'editown', 'create', 'deleteown', 'publishown', 'publishother'], Response::HTTP_FORBIDDEN]; } - private function getEditPayload($customField): array + /** + * @dataProvider putCustomItemsDataProvider + * + * @param array $permissions + */ + public function testPatchCustomItem(array $permissions, int $expectedResponse): void { - return + $customItem = $this->createCustomItem($permissions); + $response = $this->patchEntity('/api/v2/custom_items/'.$customItem->getId(), [ - 'name' => 'Custom Item Edited', 'fieldValues' => [ [ - 'id' => '/api/v2/custom_fields/'.$customField->getId(), + 'id' => '/api/v2/custom_fields/'.$customItem->getCustomObject()->getCustomFields()->first()->getId(), 'value' => 'test2', ], ], - ]; + ]); + $json = json_decode($response->getContent(), true); + + self::assertEquals($expectedResponse, $response->getStatusCode()); + + if (Response::HTTP_FORBIDDEN == $expectedResponse) { + $this->assertAccessForbiddenContent($json); + + return; + } + + $this->em->clear(); + $customItem = $this->em->getRepository(CustomItem::class)->find($json['id']); + $this->customItemModel->populateCustomFields($customItem); + $this->assertSuccessContent($json, $customItem); } /** - * @see self::testCustomItemCRUD() + * @dataProvider deleteCustomItemsDataProvider * - * @return array|array[] + * @param array $permissions */ - private function getCRUDProvider(): array - { - return [ - 'all_ok' => [ - ['viewown', 'viewother', 'editown', 'editother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'Custom Item Created', - 'test', - Response::HTTP_OK, - 'Custom Item Edited', - 'test2', - Response::HTTP_NO_CONTENT, - ], - 'no_delete' => [ - ['viewown', 'viewother', 'editown', 'editother', 'create', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'Custom Item Created', - 'test', - Response::HTTP_OK, - 'Custom Item Edited', - 'test2', - Response::HTTP_FORBIDDEN, - ], - 'no_update' => [ - ['viewown', 'viewother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'Custom Item Created', - 'test', - Response::HTTP_FORBIDDEN, - null, - null, - Response::HTTP_NO_CONTENT, - ], - 'no_create' => [ - ['viewown', 'viewother', 'editown', 'editother', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_FORBIDDEN, - '', - null, - null, - '', - null, - null, - '', - ], - ]; + public function testDeleteCustomItem(array $permissions, int $expectedResponse): void + { + $customItem = $this->createCustomItem($permissions); + $response = $this->deleteEntity('/api/v2/custom_items/'.$customItem->getId()); + $json = json_decode($response->getContent(), true); + + self::assertEquals($expectedResponse, $response->getStatusCode()); + + if (Response::HTTP_FORBIDDEN == $expectedResponse) { + $this->assertAccessForbiddenContent($json); + + return; + } + + $this->em->clear(); + $customItem = $this->em->getRepository(CustomItem::class)->find($customItem->getId()); + self::assertEquals(Response::HTTP_NO_CONTENT, $response->getStatusCode()); + self::assertNull($json); + self::assertNull($customItem); + } + + /** + * @return iterable + */ + public function deleteCustomItemsDataProvider(): iterable + { + yield [['deleteother'], Response::HTTP_NO_CONTENT]; + + yield [[], Response::HTTP_FORBIDDEN]; + + yield [['viewown', 'viewother', 'editown', 'create', 'deleteown', 'editother', 'publishown', 'publishother'], Response::HTTP_FORBIDDEN]; } private function createCustomObject(): CustomObject @@ -172,6 +254,30 @@ private function createCustomObject(): CustomObject return $customObject; } + /** + * @param array $permissions + */ + private function createCustomItem(array $permissions): CustomItem + { + $customObject = $this->createCustomObject(); + $category = $this->createCategory(); + $customField = $this->createCustomField($customObject); + $customItem = new CustomItem($customObject); + $customItem->setName('Custom Item'); + $customItem->setLanguage('en'); + $customItem->setCategory($category); + $customFieldValue = new CustomFieldValueText($customField, $customItem, 'value'); + $customItem->addCustomFieldValue($customFieldValue); + + $this->em->persist($customItem); + $this->em->flush(); + + $user = $this->getUser(); + $this->setPermission($user, 'custom_objects:'.$customObject->getId(), $permissions); + + return $customItem; + } + private function createCategory(): Category { $category = new Category(); @@ -203,4 +309,35 @@ private function createCustomField(CustomObject $customObject): CustomField return $customField; } + + /** + * @param array $json + */ + private function assertAccessForbiddenContent(array $json): void + { + self::assertEquals($json['@context'], '/api/v2/contexts/Error'); + self::assertEquals($json['@type'], 'hydra:Error'); + self::assertEquals($json['hydra:title'], 'An error occurred'); + self::assertEquals($json['hydra:description'], 'Access Denied.'); + self::assertCount(4, $json); + } + + /** + * @param array $json + */ + private function assertSuccessContent(array $json, CustomItem $customItem): void + { + self::assertEquals($json['@context'], '/api/v2/contexts/custom_items'); + self::assertEquals($json['@id'], '/api/v2/custom_items/'.$customItem->getId()); + self::assertEquals($json['@type'], 'custom_items'); + self::assertEquals($json['id'], $customItem->getId()); + self::assertEquals($json['name'], $customItem->getName()); + self::assertEquals($json['customObject'], '/api/v2/custom_objects/'.$customItem->getCustomObject()->getId()); + self::assertEquals($json['language'], 'en'); + self::assertEquals($json['category'], '/api/v2/categories/'.$customItem->getCategory()->getId()); + self::assertEquals($json['fieldValues'][0]['id'], '/api/v2/custom_fields/'.$customItem->getCustomFieldValues()->first()->getId()); + self::assertEquals($json['fieldValues'][0]['value'], $customItem->getCustomFieldValues()->first()->getValue()); + self::assertCount(9, $json); + self::assertCount(1, $json['fieldValues']); + } } diff --git a/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php b/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php index bd745f372..2560e189a 100644 --- a/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php +++ b/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php @@ -45,7 +45,7 @@ public function runTestCustomObjectCRUD( } // UPDATE $payloadUpdate = $this->getEditPayload(); - $clientUpdateResponse = $this->updateEntity($createdId, $payloadUpdate); + $clientUpdateResponse = $this->patchEntity($createdId, $payloadUpdate); $this->assertEquals($httpUpdated, $clientUpdateResponse->getStatusCode()); if ($updatedAlias) { $this->assertEquals($updatedAlias, json_decode($clientUpdateResponse->getContent())->alias); @@ -65,43 +65,43 @@ private function getCreatePayload(): array 'description' => 'string string', 'language' => 'en', 'customFields' => [ - [ - 'label' => 'Test Field 1', - 'alias' => 'customObjectTestField1', - 'type' => 'multiselect', - 'order' => 42, - 'required' => true, - 'defaultValue' => 'one', - 'options' => [ - [ - 'label' => 'one', - 'value' => 'one', - 'order' => 0, - ], - [ - 'label' => 'two', - 'value' => 'two', - 'order' => 1, - ], - ], - 'params' => [ - 'string', + [ + 'label' => 'Test Field 1', + 'alias' => 'customObjectTestField1', + 'type' => 'multiselect', + 'order' => 42, + 'required' => true, + 'defaultValue' => 'one', + 'options' => [ + [ + 'label' => 'one', + 'value' => 'one', + 'order' => 0, ], - 'isPublished' => true, - ], - [ - 'label' => 'Test Field 2', - 'alias' => 'customObjectTestField2', - 'type' => 'text', - 'order' => 43, - 'required' => true, - 'defaultValue' => 'text', - 'params' => [ - 'string', + [ + 'label' => 'two', + 'value' => 'two', + 'order' => 1, ], - 'isPublished' => true, ], + 'params' => [ + 'string', + ], + 'isPublished' => true, ], + [ + 'label' => 'Test Field 2', + 'alias' => 'customObjectTestField2', + 'type' => 'text', + 'order' => 43, + 'required' => true, + 'defaultValue' => 'text', + 'params' => [ + 'string', + ], + 'isPublished' => true, + ], + ], ]; } @@ -126,41 +126,41 @@ private function getCRUDProvider(): array { return [ 'all_ok' => [ - ['viewown', 'viewother', 'editown', 'editother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'customObjectTest', - Response::HTTP_OK, - 'customObjectTestEdited', - Response::HTTP_NO_CONTENT, - ], + ['viewown', 'viewother', 'editown', 'editother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], + Response::HTTP_CREATED, + Response::HTTP_OK, + 'customObjectTest', + Response::HTTP_OK, + 'customObjectTestEdited', + Response::HTTP_NO_CONTENT, + ], 'no_delete' => [ - ['viewown', 'viewother', 'editown', 'editother', 'create', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'customObjectTest', - Response::HTTP_OK, - 'customObjectTestEdited', - Response::HTTP_FORBIDDEN, - ], + ['viewown', 'viewother', 'editown', 'editother', 'create', 'publishown', 'publishother'], + Response::HTTP_CREATED, + Response::HTTP_OK, + 'customObjectTest', + Response::HTTP_OK, + 'customObjectTestEdited', + Response::HTTP_FORBIDDEN, + ], 'no_update' => [ - ['viewown', 'viewother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_CREATED, - Response::HTTP_OK, - 'customObjectTest', - Response::HTTP_FORBIDDEN, - null, - Response::HTTP_NO_CONTENT, - ], + ['viewown', 'viewother', 'create', 'deleteown', 'deleteother', 'publishown', 'publishother'], + Response::HTTP_CREATED, + Response::HTTP_OK, + 'customObjectTest', + Response::HTTP_FORBIDDEN, + null, + Response::HTTP_NO_CONTENT, + ], 'no_create' => [ - ['viewown', 'viewother', 'editown', 'editother', 'deleteown', 'deleteother', 'publishown', 'publishother'], - Response::HTTP_FORBIDDEN, - '', - null, - '', - null, - '', - ], + ['viewown', 'viewother', 'editown', 'editother', 'deleteown', 'deleteother', 'publishown', 'publishother'], + Response::HTTP_FORBIDDEN, + '', + null, + '', + null, + '', + ], ]; } } diff --git a/Tests/Functional/Controller/CustomItemListControllerSearchTest.php b/Tests/Functional/Controller/CustomItemListControllerSearchTest.php index 0f7f7e9cc..6fe0fb257 100644 --- a/Tests/Functional/Controller/CustomItemListControllerSearchTest.php +++ b/Tests/Functional/Controller/CustomItemListControllerSearchTest.php @@ -113,7 +113,7 @@ private function addCustomFieldValue(CustomItem $customItem, AbstractCustomField private function assertFound(CustomObject $customObject, CustomItem $customItem, string $search): void { $crawler = $this->client->request(Request::METHOD_GET, sprintf('/s/custom/object/%s/item?search=%s', $customObject->getId(), $search)); - $tableCrawler = $crawler->filterXPath('//h3[contains(text(), "Devices")]/following::table[1]'); + $tableCrawler = $crawler->filterXPath('//h1[contains(text(), "Devices")]/following::table[1]'); Assert::assertSame(1, $tableCrawler->count()); $rowCrawler = $tableCrawler->filterXPath('.//tbody/tr'); diff --git a/Tests/Functional/Controller/CustomItemListControllerShownFieldTest.php b/Tests/Functional/Controller/CustomItemListControllerShownFieldTest.php index bdf0ee8df..9b5ad02a0 100644 --- a/Tests/Functional/Controller/CustomItemListControllerShownFieldTest.php +++ b/Tests/Functional/Controller/CustomItemListControllerShownFieldTest.php @@ -4,8 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Functional\Controller; -use DateTime; -use InvalidArgumentException; use Mautic\CoreBundle\Test\MauticMysqlTestCase; use Mautic\LeadBundle\Entity\Lead; use MauticPlugin\CustomObjectsBundle\Entity\AbstractCustomFieldValue; @@ -78,7 +76,7 @@ private function assertDetailListDisplaysFields(string $type): void $showInContactDetailList = false; break; default: - throw new InvalidArgumentException(); + throw new \InvalidArgumentException(); break; } @@ -97,8 +95,8 @@ private function assertDetailListDisplaysFields(string $type): void $fieldValueBasset = $this->addCustomFieldValue($customItemAnimal, new CustomFieldValueText($customFieldBreed, $customItemAnimal, 'Basset')); $fieldValueAge = $this->addCustomFieldValue($customItemAnimal, new CustomFieldValueInt($customFieldAge, $customItemAnimal, 5)); - $fieldValueBirthDate = $this->addCustomFieldValue($customItemAnimal, new CustomFieldValueDate($customFieldBirthDate, $customItemAnimal, new DateTime('2015-02-15'))); - $fieldValueInoculation = $this->addCustomFieldValue($customItemAnimal, new CustomFieldValueDateTime($customFieldInoculation, $customItemAnimal, new DateTime('2020-09-15'))); + $fieldValueBirthDate = $this->addCustomFieldValue($customItemAnimal, new CustomFieldValueDate($customFieldBirthDate, $customItemAnimal, new \DateTime('2015-02-15'))); + $fieldValueInoculation = $this->addCustomFieldValue($customItemAnimal, new CustomFieldValueDateTime($customFieldInoculation, $customItemAnimal, new \DateTime('2020-09-15'))); $this->addCustomFieldValue($customItemAnimal, new CustomFieldValueOption($customFieldDiseases, $customItemAnimal, 'fever')); $createXref($customItemAnimal); @@ -108,7 +106,7 @@ private function assertDetailListDisplaysFields(string $type): void $this->em->flush(); $crawler = $this->client->request(Request::METHOD_GET, sprintf('/s/custom/object/%s/item?filterEntityId=%s&filterEntityType=%s', $customObjectAnimal->getId(), $relatedObject->getId(), $type)); - $tableCrawler = $crawler->filterXPath(sprintf('//h3[contains(text(), "%s")]/following::table[1]', $customObjectAnimal->getNameSingular())); + $tableCrawler = $crawler->filterXPath(sprintf('//h1[contains(text(), "%s")]/following::table[1]', $customObjectAnimal->getNameSingular())); Assert::assertSame(1, $tableCrawler->count()); $headRowCrawler = $tableCrawler->filterXPath('.//thead/tr'); diff --git a/Tests/Functional/Controller/CustomItemListControllerXrefTest.php b/Tests/Functional/Controller/CustomItemListControllerXrefTest.php index 0cf538180..9fb8afb1d 100644 --- a/Tests/Functional/Controller/CustomItemListControllerXrefTest.php +++ b/Tests/Functional/Controller/CustomItemListControllerXrefTest.php @@ -67,7 +67,7 @@ private function assertResponse(CustomObject $customObject, CustomItem $customIt $uri = sprintf('/s/custom/object/%s/item?filterEntityId=%s&filterEntityType=%s&lookup=%d', $customObject->getId(), $filterEntityId, $entityType, $lookup); $crawler = $this->client->request(Request::METHOD_GET, $uri); - $tableCrawler = $crawler->filter('table'); + $tableCrawler = $crawler->filter('div[id*="custom-item-"] table'); Assert::assertSame(1, $tableCrawler->count()); $rowCrawler = $tableCrawler->filterXPath('.//tbody/tr'); diff --git a/Tests/Functional/Controller/CustomObject/DeleteControllerTest.php b/Tests/Functional/Controller/CustomObject/DeleteControllerTest.php index a7dd5ecf0..d611be6a6 100644 --- a/Tests/Functional/Controller/CustomObject/DeleteControllerTest.php +++ b/Tests/Functional/Controller/CustomObject/DeleteControllerTest.php @@ -33,8 +33,8 @@ public function testDeleteChildObject() // Open Custom Object listing page verify that both parent and child objects are listed in Custom Objects table. $crawler = $this->client->request(Request::METHOD_GET, '/s/custom/object'); - $this->assertStringContainsString('Products', $crawler->filterXPath('//*[@id="custom-objects-table"]/tbody/tr[1]/td[2]/div/a')->text()); - $this->assertStringContainsString('Electronics', $crawler->filterXPath('//*[@id="custom-objects-table"]/tbody/tr[2]/td[2]/div/a')->text()); + $this->assertStringContainsString('Electronics', $crawler->filterXPath('//*[@id="custom-objects-table"]/tbody/tr[1]/td[2]/div/a')->text()); + $this->assertStringContainsString('Products', $crawler->filterXPath('//*[@id="custom-objects-table"]/tbody/tr[2]/td[2]/div/a')->text()); // Delete the Child Custom Object $this->client->request(Request::METHOD_POST, sprintf('/s/custom/object/delete/%s', $childObject->getId())); diff --git a/Tests/Functional/Controller/CustomObjectFormTest.php b/Tests/Functional/Controller/CustomObjectFormTest.php index 0a887f7bd..32017b8cb 100644 --- a/Tests/Functional/Controller/CustomObjectFormTest.php +++ b/Tests/Functional/Controller/CustomObjectFormTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Functional\Controller; -use DateTime; use Mautic\CoreBundle\Test\MauticMysqlTestCase; use MauticPlugin\CustomObjectsBundle\Entity\CustomFieldOption; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; @@ -886,12 +885,12 @@ private function assertCustomObject(array $expected, int $id): void $defaultValue = $customField->getDefaultValue(); switch ($customField->getType()) { case 'date': - $this->assertInstanceOf(DateTime::class, $defaultValue); + $this->assertInstanceOf(\DateTime::class, $defaultValue); $this->assertSame($expectedCf['defaultValue'], $defaultValue->format('Y-m-d')); break; case 'datetime': - $this->assertInstanceOf(DateTime::class, $defaultValue); + $this->assertInstanceOf(\DateTime::class, $defaultValue); $this->assertSame($expectedCf['defaultValue'], $defaultValue->format('Y-m-d H:i')); break; diff --git a/Tests/Functional/DataFixtures/ORM/Data/custom-item-relation-filter-query-builder-fixture-2.yml b/Tests/Functional/DataFixtures/ORM/Data/custom-item-relation-filter-query-builder-fixture-2.yml index 6ea0fc204..73a264473 100644 --- a/Tests/Functional/DataFixtures/ORM/Data/custom-item-relation-filter-query-builder-fixture-2.yml +++ b/Tests/Functional/DataFixtures/ORM/Data/custom-item-relation-filter-query-builder-fixture-2.yml @@ -216,6 +216,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'Price = 1000' alias: 'price-eq-1000' + public_name: 'price-eq-1000' filters: 0: glue : 'and' @@ -233,6 +234,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'Order name = Ordered plug' alias: 'order-plug-name-eq' + public_name: 'order-plug-name-eq' filters: # a:1:{i:0;a:6:{s:4:"glue";s:3:"and";s:5:"field";s:5:"cmo_2";s:6:"object";s:13:"custom_object";s:4:"type";s:4:"text";s:8:"operator";s:1:"=";s:10:"properties";a:1:{s:6:"filter";s:12:"Ordered plug";}}} 0: glue : 'and' @@ -249,6 +251,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'Date < 1990' alias: 'date-lt-1990' + public_name: 'date-lt-1990' filters: # a:1:{i:0;a:6:{s:4:"glue";s:3:"and";s:5:"field";s:5:"cmf_2";s:6:"object";s:13:"custom_object";s:4:"type";s:4:"date";s:8:"operator";s:2:"lt";s:10:"properties";a:1:{s:6:"filter";s:4:"1990";}}} 0: glue : 'and' @@ -265,6 +268,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'DateTime > 1990' alias: 'datetime-gt-1990' + public_name: 'datetime-gt-1990' filters: 0: glue : 'and' @@ -281,6 +285,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'Price > 500' alias: 'price-greater-500' + public_name: 'price-greater-500' filters: # a:1:{i:0;a:6:{s:4:"glue";s:3:"and";s:5:"field";s:5:"cmf_1";s:6:"object";s:13:"custom_object";s:4:"type";s:3:"int";s:8:"operator";s:2:"gt";s:10:"properties";a:1:{s:6:"filter";s:3:"500";}}} 0: glue : 'and' @@ -297,6 +302,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'Price = 500' alias: 'price-eq-500' + public_name: 'price-eq-500' filters: 0: glue : 'and' @@ -313,6 +319,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'Price > 1000' alias: 'price-greater-1000' + public_name: 'price-greater-1000' filters: 0: glue : 'and' @@ -329,6 +336,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'Price <= 1000' alias: 'price-lte-1000' + public_name: 'price-lte-1000' filters: 0: glue : 'and' @@ -345,6 +353,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'Price < 500' alias: 'price-lt-500' + public_name: 'price-lt-500' filters: 0: glue : 'and' @@ -361,6 +370,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'Multiselect = 1' alias: 'option-in-1' + public_name: 'option-in-1' filters: # a:1:{i:0;a:8:{s:6:"object";s:13:"custom_object";s:4:"glue";s:3:"and";s:5:"field";s:5:"cmf_1";s:4:"type";s:11:"multiselect";s:8:"operator";s:2:"in";s:10:"properties";a:1:{s:6:"filter";a:1:{i:0;s:1:"1";}}s:6:"filter";a:1:{i:0;s:1:"1";}s:7:"display";N;}} 0: glue : 'and' @@ -381,6 +391,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'Text = text' alias: 'text-eq-text' + public_name: 'text-eq-tex' filters: 0: glue : 'and' @@ -398,6 +409,7 @@ Mautic\LeadBundle\Entity\LeadList: is_published: true name: 'Combined Price = 1000 and Date = 2020-08-13' alias: 'combined' + public_name: 'combined' filters: 0: glue : 'and' diff --git a/Tests/Functional/DataFixtures/ORM/Data/custom_fields.yml b/Tests/Functional/DataFixtures/ORM/Data/custom_fields.yml index a9c54cf48..ae7da7f5c 100644 --- a/Tests/Functional/DataFixtures/ORM/Data/custom_fields.yml +++ b/Tests/Functional/DataFixtures/ORM/Data/custom_fields.yml @@ -5,7 +5,7 @@ MauticPlugin\CustomObjectsBundle\Entity\CustomField: date_added: '' label: ' Text' alias: 'text_1' - type: 'tect' + type: 'text' custom_field2: custom_object: '@custom_object1' is_published: true @@ -68,4 +68,4 @@ MauticPlugin\CustomObjectsBundle\Entity\CustomField: date_added: '' label: ' Country' alias: 'country_11' - type: 'country' \ No newline at end of file + type: 'country' diff --git a/Tests/Functional/DataFixtures/Traits/CustomObjectsTrait.php b/Tests/Functional/DataFixtures/Traits/CustomObjectsTrait.php index 7d6fe4588..d6f2508ba 100644 --- a/Tests/Functional/DataFixtures/Traits/CustomObjectsTrait.php +++ b/Tests/Functional/DataFixtures/Traits/CustomObjectsTrait.php @@ -65,6 +65,7 @@ public function createCustomItem(ContainerInterface $container, CustomObject $cu /** @var CustomItemModel $customItemModel */ $customItemModel = $container->get('mautic.custom.model.item'); + return $customItemModel->save($customItem); } diff --git a/Tests/Functional/DataFixtures/Traits/FixtureObjectsTrait.php b/Tests/Functional/DataFixtures/Traits/FixtureObjectsTrait.php index b0dac57f3..6bcae7748 100644 --- a/Tests/Functional/DataFixtures/Traits/FixtureObjectsTrait.php +++ b/Tests/Functional/DataFixtures/Traits/FixtureObjectsTrait.php @@ -32,6 +32,8 @@ trait FixtureObjectsTrait */ public function setFixtureObjects(array $objects): void { + $this->skipIfMissingDependency(); + foreach ($objects as $key => $object) { $this->objects[get_class($object)][$key] = $object; $this->entityMap[$key] = get_class($object); @@ -45,6 +47,8 @@ public function setFixtureObjects(array $objects): void */ public function getFixturesByEntityClassName(string $type): array { + $this->skipIfMissingDependency(); + if (!isset($this->objects[$type])) { throw new FixtureNotFoundException('No fixtures of type '.$type.' defined'); } @@ -57,6 +61,8 @@ public function getFixturesByEntityClassName(string $type): array */ public function getFixtureByEntityClassNameAndIndex(string $type, int $index): CommonEntity { + $this->skipIfMissingDependency(); + $fixtures = $this->getFixturesByEntityClassName($type); $fixtures = array_values($fixtures); @@ -75,6 +81,8 @@ public function getFixtureByEntityClassNameAndIndex(string $type, int $index): C */ public function getFixtureById(string $id): UniqueEntityInterface { + $this->skipIfMissingDependency(); + if (!isset($this->entityMap[$id])) { throw new FixtureNotFoundException('No fixture with id "'.$id.'"" defined'); } @@ -87,10 +95,12 @@ public function getFixtureById(string $id): UniqueEntityInterface */ public function getFixturesInUnloadableOrder(): array { + $this->skipIfMissingDependency(); + $entities = []; $orderedKeys = $this->entityMap; - array_reverse($orderedKeys, true); + $orderedKeys = array_reverse($orderedKeys, true); foreach ($orderedKeys as $key => $type) { $entities[$key] = $this->objects[$type][$key]; } @@ -100,6 +110,8 @@ public function getFixturesInUnloadableOrder(): array private function getFixturesDirectory(): string { + $this->skipIfMissingDependency(); + /** @var KernelInterface $kernel */ $kernel = $this->getContainer()->get('kernel'); $pluginDirectory = $kernel->locateResource('@CustomObjectsBundle'); @@ -110,4 +122,11 @@ private function getFixturesDirectory(): string return $pluginDirectory.'/Tests/Functional/DataFixtures/ORM/Data'; } + + private function skipIfMissingDependency(): void + { + if (!self::$container->has('fidry_alice_data_fixtures.loader.doctrine')) { + $this->markTestSkipped('This test requires the theofidry/alice-data-fixtures package'); + } + } } diff --git a/Tests/Functional/EventListener/ApiSubscriberTest.php b/Tests/Functional/EventListener/ApiSubscriberTest.php index 862287795..6b3b2ba9b 100644 --- a/Tests/Functional/EventListener/ApiSubscriberTest.php +++ b/Tests/Functional/EventListener/ApiSubscriberTest.php @@ -347,7 +347,7 @@ public function testCreatingContactWithCustomItemsAndEditAndClearValues(): void $this->assertSame([], $customItemFromResponse['attributes']['multiselect-test-field']); $this->assertSame('', $customItemFromResponse['attributes']['select-test-field']); $this->assertSame('', $customItemFromResponse['attributes']['phone-number-test-field']); - $this->assertSame(null, $customItemFromResponse['attributes']['number-test-field']); + $this->assertSame(0, $customItemFromResponse['attributes']['number-test-field']); $this->assertSame('', $customItemFromResponse['attributes']['hidden-test-field']); $this->assertSame('', $customItemFromResponse['attributes']['email-test-field']); $this->assertSame(null, $customItemFromResponse['attributes']['date-test-field']); diff --git a/Tests/Functional/EventListener/CampaignConditionTest.php b/Tests/Functional/EventListener/CampaignConditionTest.php index f95926bbf..dd464be5e 100644 --- a/Tests/Functional/EventListener/CampaignConditionTest.php +++ b/Tests/Functional/EventListener/CampaignConditionTest.php @@ -5,17 +5,45 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Functional\EventListener; use Mautic\CoreBundle\Test\MauticMysqlTestCase; +use Mautic\CoreBundle\Test\Session\FixedMockFileSessionStorage; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Tests\Functional\DataFixtures\Traits\CustomObjectsTrait; use PHPUnit\Framework\Assert; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; +use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy; class CampaignConditionTest extends MauticMysqlTestCase { use CustomObjectsTrait; + protected function setUp(): void + { + // Disable API just for specific test. + $this->configParams['api_enabled'] = 'testDisabledApi' !== $this->getName(); + + static::getContainer()->set( + 'session', + new Session( + new class() extends FixedMockFileSessionStorage { + } + ) + ); + + parent::setUp(); + } + public function testConditionForm(): void { + $session = self::$container->get('session'); + // @phpstan-ignore-next-line Fixing "cannot serialize anonymous function in \Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage::save() + $session->__construct(new MockArraySessionStorage()); + + $sessionAuthenticationStrategy = self::$container->get('security.authentication.session_strategy'); + // @phpstan-ignore-next-line Prevent clearing CSRF token storage in \Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy::onAuthentication() + $sessionAuthenticationStrategy->__construct(SessionAuthenticationStrategy::MIGRATE); + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Campaign test object'); $crawler = $this->client->request( Request::METHOD_GET, @@ -57,4 +85,35 @@ public function testConditionForm(): void Assert::assertSame('=', $body['event']['properties']['properties']['operator']); Assert::assertSame('unicorn', $body['event']['properties']['properties']['value']); } + + public function testVerifyDataOperatorAttrIsAvailableForFields(): void + { + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Campaign test object'); + $crawler = $this->client->request( + Request::METHOD_GET, + 's/campaigns/events/new', + [ + 'campaignId' => 'mautic_041b2a401f680fb0b644654af5ba0892f31f0697', + 'type' => "custom_item.{$customObject->getId()}.fieldvalue", + 'eventType' => 'condition', + 'anchor' => 'leadsource', + 'anchorEventType' => 'source', + ], + [], + $this->createAjaxHeaders() + ); + + Assert::assertTrue($this->client->getResponse()->isOk(), $this->client->getResponse()->getContent()); + + $html = json_decode($this->client->getResponse()->getContent(), true)['newContent']; + + $crawler->addHtmlContent($html); + + $options = $crawler->filter('#campaignevent_properties_field')->filter('option'); // ->attr('data-operators'); + + /** @var \DOMElement $option */ + foreach ($options as $option) { + Assert::assertNotEmpty($option->getAttribute('data-operators')); + } + } } diff --git a/Tests/Functional/EventListener/ContactSubscriberTest.php b/Tests/Functional/EventListener/ContactSubscriberTest.php new file mode 100644 index 000000000..b0e95711a --- /dev/null +++ b/Tests/Functional/EventListener/ContactSubscriberTest.php @@ -0,0 +1,81 @@ +customItemModel = self::$container->get('mautic.custom.model.item'); + $this->contactMerger = self::$container->get('mautic.lead.merger'); + $this->customItemXrefContactRepository = self::$container->get('custom_item.xref.contact.repository'); + } + + public function testMergingContactsWhenLoserHasItemAndWinnerHasNot(): void + { + $winner = $this->createContact('john@doe.email'); + $loser = $this->createContact('anna@muck.email'); + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Campaign test object'); + $customItem = new CustomItem($customObject); + + $customItem->setName('Campaign test item'); + $customItem = $this->customItemModel->save($customItem); + $this->customItemModel->linkEntity($customItem, 'contact', (int) $loser->getId()); + + $this->contactMerger->merge($winner, $loser); + + Assert::assertCount(0, $this->customItemXrefContactRepository->findBy(['contact' => $loser->getId()])); + Assert::assertCount(1, $this->customItemXrefContactRepository->findBy(['contact' => $winner->getId()])); + } + + public function testMergingContactsWhenLoserHasItemAndWinnerTheSameToo(): void + { + $winner = $this->createContact('john@doe.email'); + $loser = $this->createContact('anna@muck.email'); + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Campaign test object'); + $customItem = new CustomItem($customObject); + + $customItem->setName('Campaign test item'); + $customItem = $this->customItemModel->save($customItem); + $this->customItemModel->linkEntity($customItem, 'contact', (int) $loser->getId()); + $this->customItemModel->linkEntity($customItem, 'contact', (int) $winner->getId()); + + $this->contactMerger->merge($winner, $loser); + + Assert::assertCount(0, $this->customItemXrefContactRepository->findBy(['contact' => $loser->getId()])); + Assert::assertCount(1, $this->customItemXrefContactRepository->findBy(['contact' => $winner->getId()])); + } + + private function createContact(string $email): Lead + { + /** @var LeadModel $contactModel */ + $contactModel = self::$container->get('mautic.lead.model.lead'); + $contact = new Lead(); + $contact->setEmail($email); + $contactModel->saveEntity($contact); + + return $contact; + } +} diff --git a/Tests/Functional/EventListener/DynamicContentSubscriberTest.php b/Tests/Functional/EventListener/DynamicContentSubscriberTest.php index 46a9460ae..cd09ae3ce 100644 --- a/Tests/Functional/EventListener/DynamicContentSubscriberTest.php +++ b/Tests/Functional/EventListener/DynamicContentSubscriberTest.php @@ -4,17 +4,552 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Functional\EventListener; -use Mautic\DynamicContentBundle\DynamicContentEvents; +use Mautic\CoreBundle\Test\MauticMysqlTestCase; +use Mautic\DynamicContentBundle\Event\ContactFiltersEvaluateEvent; +use Mautic\LeadBundle\Entity\Lead; +use Mautic\LeadBundle\Model\LeadModel; +use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\EventListener\DynamicContentSubscriber; -use PHPUnit\Framework\TestCase; +use MauticPlugin\CustomObjectsBundle\Model\CustomFieldValueModel; +use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; +use MauticPlugin\CustomObjectsBundle\Tests\Functional\DataFixtures\Traits\CustomObjectsTrait; -class DynamicContentSubscriberTest extends TestCase +#[\AllowDynamicProperties] +class DynamicContentSubscriberTest extends MauticMysqlTestCase { - public function testSubscribesToEvent(): void + use CustomObjectsTrait; + + private CustomItemModel $customItemModel; + private CustomFieldValueModel $customFieldValueModel; + private DynamicContentSubscriber $subscriber; + + protected function setUp(): void + { + parent::setUp(); + + $this->customItemModel = self::$container->get('mautic.custom.model.item'); + $this->customFieldValueModel = self::$container->get('mautic.custom.model.field.value'); + $this->subscriber = self::$container->get(DynamicContentSubscriber::class); + } + + public function testVariousOperators(): void + { + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Product'); + $contact = $this->createContact('operators@example.com'); + $customItem = new CustomItem($customObject); + $customItem->setName('Test Item'); + $this->customFieldValueModel->createValuesForItem($customItem); + + $textValue = $customItem->findCustomFieldValueForFieldAlias('text-test-field'); + $urlValue = $customItem->findCustomFieldValueForFieldAlias('url-test-field'); + $dateValue = $customItem->findCustomFieldValueForFieldAlias('date-test-field'); + $datetimeValue = $customItem->findCustomFieldValueForFieldAlias('datetime-test-field'); + $multiselectValue = $customItem->findCustomFieldValueForFieldAlias('multiselect-test-field'); + + $textValue->setValue('abracadabra'); + $dateValue->setValue('2019-07-17'); + $datetimeValue->setValue('2019-07-17 13:00:00'); + $multiselectValue->setValue(['option_b']); + // urlValue left empty intentionally + + $customItem = $this->customItemModel->save($customItem); + $this->customItemModel->linkEntity($customItem, 'contact', (int) $contact->getId()); + + $textFieldId = $textValue->getCustomField()->getId(); + $urlFieldId = $urlValue->getCustomField()->getId(); + $dateFieldId = $dateValue->getCustomField()->getId(); + $datetimeFieldId = $datetimeValue->getCustomField()->getId(); + $multiselectFieldId = $multiselectValue->getCustomField()->getId(); + + // = match + $this->assertMatched($contact, $textFieldId, 'text', '=', 'abracadabra'); + + // = no match + $this->assertNotMatched($contact, $textFieldId, 'text', '=', 'unicorn'); + + // != match + $this->assertMatched($contact, $textFieldId, 'text', '!=', 'unicorn'); + + // != no match + $this->assertNotMatched($contact, $textFieldId, 'text', '!=', 'abracadabra'); + + // empty — url field has no value + $this->assertMatched($contact, $urlFieldId, 'text', 'empty', null); + + // !empty — text field has a value + $this->assertMatched($contact, $textFieldId, 'text', '!empty', null); + + // !empty — url field is empty, so !empty should not match + $this->assertNotMatched($contact, $urlFieldId, 'text', '!empty', null); + + // startsWith match + $this->assertMatched($contact, $textFieldId, 'text', 'startsWith', 'abra'); + + // startsWith no match + $this->assertNotMatched($contact, $textFieldId, 'text', 'startsWith', 'unicorn'); + + // endsWith match + $this->assertMatched($contact, $textFieldId, 'text', 'endsWith', 'cadabra'); + + // endsWith no match + $this->assertNotMatched($contact, $textFieldId, 'text', 'endsWith', 'unicorn'); + + // contains match + $this->assertMatched($contact, $textFieldId, 'text', 'contains', 'cada'); + + // contains no match + $this->assertNotMatched($contact, $textFieldId, 'text', 'contains', 'unicorn'); + + // like with % wildcard match + $this->assertMatched($contact, $textFieldId, 'text', 'like', 'abra%'); + + // like no match + $this->assertNotMatched($contact, $textFieldId, 'text', 'like', 'unicorn%'); + + // !like no match (value matches pattern, so !like is false) + $this->assertNotMatched($contact, $textFieldId, 'text', '!like', 'abra%'); + + // !like match (value does not match pattern) + $this->assertMatched($contact, $textFieldId, 'text', '!like', 'unicorn%'); + + // in (multiselect) match + $this->assertMatched($contact, $multiselectFieldId, 'multiselect', 'in', ['option_b']); + + // in (multiselect) no match + $this->assertNotMatched($contact, $multiselectFieldId, 'multiselect', 'in', ['option_a']); + + // !in (multiselect) match + $this->assertMatched($contact, $multiselectFieldId, 'multiselect', '!in', ['option_a']); + + // !in (multiselect) no match (value is in list) + $this->assertNotMatched($contact, $multiselectFieldId, 'multiselect', '!in', ['option_b']); + + // date lt match + $this->assertMatched($contact, $dateFieldId, 'date', 'lt', '2019-08-05'); + + // date lt no match + $this->assertNotMatched($contact, $dateFieldId, 'date', 'lt', '2019-06-05'); + + // date gt match + $this->assertMatched($contact, $dateFieldId, 'date', 'gt', '2019-06-05'); + + // date gt no match + $this->assertNotMatched($contact, $dateFieldId, 'date', 'gt', '2019-08-05'); + + // datetime gt match + $this->assertMatched($contact, $datetimeFieldId, 'datetime', 'gt', '2019-07-16 13:00:00'); + + // datetime gt no match + $this->assertNotMatched($contact, $datetimeFieldId, 'datetime', 'gt', '2019-07-18 13:00:00'); + } + + public function testAndFiltersAllMustMatch(): void + { + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Product'); + $contact = $this->createContact('and-match@example.com'); + $customItem = new CustomItem($customObject); + $customItem->setName('Test Item'); + $this->customFieldValueModel->createValuesForItem($customItem); + + $textValue = $customItem->findCustomFieldValueForFieldAlias('text-test-field'); + $urlValue = $customItem->findCustomFieldValueForFieldAlias('url-test-field'); + $textValue->setValue('abracadabra'); + $urlValue->setValue('https://example.com'); + + $customItem = $this->customItemModel->save($customItem); + $this->customItemModel->linkEntity($customItem, 'contact', (int) $contact->getId()); + + $filters = [ + [ + 'glue' => 'and', + 'field' => 'cmf_'.$textValue->getCustomField()->getId(), + 'object' => 'custom_object', + 'type' => 'text', + 'filter' => 'abracadabra', + 'display' => null, + 'operator' => '=', + ], + [ + 'glue' => 'and', + 'field' => 'cmf_'.$urlValue->getCustomField()->getId(), + 'object' => 'custom_object', + 'type' => 'text', + 'filter' => null, + 'display' => null, + 'operator' => '!empty', + ], + ]; + + $event = new ContactFiltersEvaluateEvent($filters, $contact); + $this->subscriber->evaluateFilters($event); + + $this->assertTrue($event->isEvaluated()); + $this->assertTrue($event->isMatched(), 'Both AND conditions are true, should match'); + } + + public function testAndFiltersOneFailsNoMatch(): void + { + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Product'); + $contact = $this->createContact('and-no-match@example.com'); + $customItem = new CustomItem($customObject); + $customItem->setName('Test Item'); + $this->customFieldValueModel->createValuesForItem($customItem); + + $textValue = $customItem->findCustomFieldValueForFieldAlias('text-test-field'); + $urlValue = $customItem->findCustomFieldValueForFieldAlias('url-test-field'); + $textValue->setValue('abracadabra'); + // urlValue left empty intentionally + + $customItem = $this->customItemModel->save($customItem); + $this->customItemModel->linkEntity($customItem, 'contact', (int) $contact->getId()); + + $filters = [ + [ + 'glue' => 'and', + 'field' => 'cmf_'.$textValue->getCustomField()->getId(), + 'object' => 'custom_object', + 'type' => 'text', + 'filter' => 'abracadabra', + 'display' => null, + 'operator' => '=', + ], + [ + 'glue' => 'and', + 'field' => 'cmf_'.$urlValue->getCustomField()->getId(), + 'object' => 'custom_object', + 'type' => 'text', + 'filter' => null, + 'display' => null, + 'operator' => '!empty', // url is empty, so this fails + ], + ]; + + $event = new ContactFiltersEvaluateEvent($filters, $contact); + $this->subscriber->evaluateFilters($event); + + $this->assertTrue($event->isEvaluated()); + $this->assertFalse($event->isMatched(), 'One AND condition fails, should not match'); + } + + public function testOrFiltersSecondGroupMatches(): void + { + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Product'); + $contact = $this->createContact('or-match@example.com'); + $customItem = new CustomItem($customObject); + $customItem->setName('Test Item'); + $this->customFieldValueModel->createValuesForItem($customItem); + + $textValue = $customItem->findCustomFieldValueForFieldAlias('text-test-field'); + $urlValue = $customItem->findCustomFieldValueForFieldAlias('url-test-field'); + $textValue->setValue('abracadabra'); + $urlValue->setValue('https://example.com'); + + $customItem = $this->customItemModel->save($customItem); + $this->customItemModel->linkEntity($customItem, 'contact', (int) $contact->getId()); + + $filters = [ + [ + 'glue' => 'and', + 'field' => 'cmf_'.$textValue->getCustomField()->getId(), + 'object' => 'custom_object', + 'type' => 'text', + 'filter' => 'unicorn', // first group fails + 'display' => null, + 'operator' => '=', + ], + [ + 'glue' => 'or', // starts a new group + 'field' => 'cmf_'.$urlValue->getCustomField()->getId(), + 'object' => 'custom_object', + 'type' => 'text', + 'filter' => null, + 'display' => null, + 'operator' => '!empty', // second group passes + ], + ]; + + $event = new ContactFiltersEvaluateEvent($filters, $contact); + $this->subscriber->evaluateFilters($event); + + $this->assertTrue($event->isEvaluated()); + $this->assertTrue($event->isMatched(), 'Second OR group passes, overall result should match'); + } + + public function testMultipleLinkedItemsAnyMatchWins(): void + { + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Product'); + $contact = $this->createContact('multi-item@example.com'); + + $itemA = new CustomItem($customObject); + $itemA->setName('Item A'); + $this->customFieldValueModel->createValuesForItem($itemA); + $itemA->findCustomFieldValueForFieldAlias('text-test-field')->setValue('basic'); + $itemA = $this->customItemModel->save($itemA); + $this->customItemModel->linkEntity($itemA, 'contact', (int) $contact->getId()); + + $itemB = new CustomItem($customObject); + $itemB->setName('Item B'); + $this->customFieldValueModel->createValuesForItem($itemB); + $textValueB = $itemB->findCustomFieldValueForFieldAlias('text-test-field'); + $textValueB->setValue('premium'); + $itemB = $this->customItemModel->save($itemB); + $this->customItemModel->linkEntity($itemB, 'contact', (int) $contact->getId()); + + $filters = [ + [ + 'glue' => 'and', + 'field' => 'cmf_'.$textValueB->getCustomField()->getId(), + 'object' => 'custom_object', + 'type' => 'text', + 'filter' => 'premium', + 'display' => null, + 'operator' => '=', + ], + ]; + + $event = new ContactFiltersEvaluateEvent($filters, $contact); + $this->subscriber->evaluateFilters($event); + + $this->assertTrue($event->isEvaluated()); + $this->assertTrue($event->isMatched(), 'When any linked item matches, overall result should match'); + } + + public function testEmptyOperatorMatchesContactWithNoLinkedItems(): void + { + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Product'); + $contact = $this->createContact('no-items@example.com'); + // No custom item is created or linked to this contact + + // To make hasCustomObjectFilters() pass (so the subscriber takes ownership), + // we still need a filter with a valid custom field ID. Create a throwaway item + // just to get a field ID, but don't link it to this contact. + $tempItem = new CustomItem($customObject); + $tempItem->setName('Temp'); + $this->customFieldValueModel->createValuesForItem($tempItem); + $textValue = $tempItem->findCustomFieldValueForFieldAlias('text-test-field'); + $this->customItemModel->save($tempItem); + // Not linked to $contact + + $filters = [ + [ + 'glue' => 'and', + 'field' => 'cmf_'.$textValue->getCustomField()->getId(), + 'object' => 'custom_object', + 'type' => 'text', + 'filter' => null, + 'display' => null, + 'operator' => 'empty', + ], + ]; + + $event = new ContactFiltersEvaluateEvent($filters, $contact); + $this->subscriber->evaluateFilters($event); + + $this->assertTrue($event->isEvaluated()); + $this->assertTrue($event->isMatched(), 'Contact with no linked items should match the "empty" operator'); + } + + public function testAlreadyEvaluatedEventIsSkipped(): void + { + // No DB setup needed — the subscriber bails out before touching the DB. + $contact = new Lead(); + $event = new ContactFiltersEvaluateEvent([], $contact); + $event->setIsEvaluated(true); // already handled by another listener + $event->setIsMatched(false); // prior result was false + + $this->subscriber->evaluateFilters($event); + + $this->assertFalse($event->isMatched(), 'Subscriber must not overwrite a result already set by another listener'); + } + + public function testRegexpOperator(): void + { + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Product'); + $contact = $this->createContact('regexp@example.com'); + $customItem = new CustomItem($customObject); + $customItem->setName('Test Item'); + $this->customFieldValueModel->createValuesForItem($customItem); + + $textValue = $customItem->findCustomFieldValueForFieldAlias('text-test-field'); + $textValue->setValue('abracadabra'); + $customItem = $this->customItemModel->save($customItem); + $this->customItemModel->linkEntity($customItem, 'contact', (int) $contact->getId()); + + $fieldId = $textValue->getCustomField()->getId(); + + // regexp match + $this->assertMatched($contact, $fieldId, 'text', 'regexp', 'abra.*cadabra'); + + // regexp no match + $this->assertNotMatched($contact, $fieldId, 'text', 'regexp', '^unicorn'); + + // !regexp match (value does not match pattern) + $this->assertMatched($contact, $fieldId, 'text', '!regexp', '^unicorn'); + + // !regexp no match (value matches pattern) + $this->assertNotMatched($contact, $fieldId, 'text', '!regexp', 'abra.*cadabra'); + } + + public function testNumberFieldComparisons(): void + { + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Product'); + $contact = $this->createContact('number@example.com'); + $customItem = new CustomItem($customObject); + $customItem->setName('Test Item'); + $this->customFieldValueModel->createValuesForItem($customItem); + + $intValue = $customItem->findCustomFieldValueForFieldAlias('number-test-field'); + $intValue->setValue(42); + $customItem = $this->customItemModel->save($customItem); + $this->customItemModel->linkEntity($customItem, 'contact', (int) $contact->getId()); + + $fieldId = $intValue->getCustomField()->getId(); + + // = match / no match + $this->assertMatched($contact, $fieldId, 'int', '=', 42); + $this->assertNotMatched($contact, $fieldId, 'int', '=', 99); + + // gt / gte + $this->assertMatched($contact, $fieldId, 'int', 'gt', 10); + $this->assertNotMatched($contact, $fieldId, 'int', 'gt', 42); + $this->assertMatched($contact, $fieldId, 'int', 'gte', 42); + $this->assertNotMatched($contact, $fieldId, 'int', 'gte', 43); + + // lt / lte + $this->assertMatched($contact, $fieldId, 'int', 'lt', 99); + $this->assertNotMatched($contact, $fieldId, 'int', 'lt', 42); + $this->assertMatched($contact, $fieldId, 'int', 'lte', 42); + $this->assertNotMatched($contact, $fieldId, 'int', 'lte', 41); + } + + public function testOrFiltersFirstGroupPassesSecondFails(): void + { + $customObject = $this->createCustomObjectWithAllFields(self::$container, 'Product'); + $contact = $this->createContact('or-first-passes@example.com'); + $customItem = new CustomItem($customObject); + $customItem->setName('Test Item'); + $this->customFieldValueModel->createValuesForItem($customItem); + + $textValue = $customItem->findCustomFieldValueForFieldAlias('text-test-field'); + $urlValue = $customItem->findCustomFieldValueForFieldAlias('url-test-field'); + $textValue->setValue('abracadabra'); + // urlValue left empty + + $customItem = $this->customItemModel->save($customItem); + $this->customItemModel->linkEntity($customItem, 'contact', (int) $contact->getId()); + + $filters = [ + [ + 'glue' => 'and', + 'field' => 'cmf_'.$textValue->getCustomField()->getId(), + 'object' => 'custom_object', + 'type' => 'text', + 'filter' => 'abracadabra', + 'display' => null, + 'operator' => '=', // first group passes + ], + [ + 'glue' => 'or', // starts a second group + 'field' => 'cmf_'.$urlValue->getCustomField()->getId(), + 'object' => 'custom_object', + 'type' => 'text', + 'filter' => null, + 'display' => null, + 'operator' => '!empty', // second group fails (url is empty) + ], + ]; + + $event = new ContactFiltersEvaluateEvent($filters, $contact); + $this->subscriber->evaluateFilters($event); + + $this->assertTrue($event->isEvaluated()); + $this->assertTrue($event->isMatched(), 'First OR group passes — overall result must be true even though second group fails'); + } + + public function testEvaluateFiltersSkipsEventWithNoCustomObjectFilters(): void + { + $contact = $this->createContact('test-skip@example.com'); + + $filters = [ + [ + 'glue' => 'and', + 'field' => 'email', + 'object' => 'lead', + 'type' => 'email', + 'filter' => 'test-skip@example.com', + 'display' => null, + 'operator' => '=', + ], + ]; + + $event = new ContactFiltersEvaluateEvent($filters, $contact); + $this->subscriber->evaluateFilters($event); + + $this->assertFalse($event->isEvaluated(), 'Subscriber should not take ownership when no custom object filters are present'); + } + + /** + * @param mixed $filterValue + */ + private function assertMatched(Lead $contact, int $fieldId, string $type, string $operator, $filterValue): void + { + $event = new ContactFiltersEvaluateEvent( + $this->buildFilter($fieldId, $type, $operator, $filterValue), + $contact + ); + $this->subscriber->evaluateFilters($event); + + $this->assertTrue( + $event->isMatched(), + "Expected match for operator '{$operator}' with filter value '".json_encode($filterValue)."'" + ); + } + + /** + * @param mixed $filterValue + */ + private function assertNotMatched(Lead $contact, int $fieldId, string $type, string $operator, $filterValue): void + { + $event = new ContactFiltersEvaluateEvent( + $this->buildFilter($fieldId, $type, $operator, $filterValue), + $contact + ); + $this->subscriber->evaluateFilters($event); + + $this->assertFalse( + $event->isMatched(), + "Expected no match for operator '{$operator}' with filter value '".json_encode($filterValue)."'" + ); + } + + /** + * @param mixed $filterValue + * + * @return array> + */ + private function buildFilter(int $fieldId, string $type, string $operator, $filterValue): array + { + return [ + [ + 'glue' => 'and', + 'field' => 'cmf_'.$fieldId, + 'object' => 'custom_object', + 'type' => $type, + 'filter' => $filterValue, + 'display' => null, + 'operator' => $operator, + ], + ]; + } + + private function createContact(string $email): Lead { - $eventSubscriptions = DynamicContentSubscriber::getSubscribedEvents(); - $methodName = $eventSubscriptions[DynamicContentEvents::ON_CONTACTS_FILTER_EVALUATE][0]; + /** @var LeadModel $contactModel */ + $contactModel = self::$container->get('mautic.lead.model.lead'); + $contact = new Lead(); + $contact->setEmail($email); + $contactModel->saveEntity($contact); - $this->assertSame('evaluateFilters', $methodName); + return $contact; } } diff --git a/Tests/Functional/EventListener/FilterOperatorSubscriberTest.php b/Tests/Functional/EventListener/FilterOperatorSubscriberTest.php index c1f663b32..eeeb646c8 100644 --- a/Tests/Functional/EventListener/FilterOperatorSubscriberTest.php +++ b/Tests/Functional/EventListener/FilterOperatorSubscriberTest.php @@ -4,31 +4,39 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Functional\EventListener; +use Mautic\CoreBundle\Helper\CommandHelper; use Mautic\CoreBundle\Test\MauticMysqlTestCase; use Mautic\LeadBundle\Entity\Lead; +use Mautic\LeadBundle\Entity\LeadField; use Mautic\LeadBundle\Entity\LeadList; use Mautic\LeadBundle\Entity\ListLead; +use MauticPlugin\CustomObjectsBundle\CustomFieldType\CustomFieldTypeInterface; +use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; +use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider; +use MauticPlugin\CustomObjectsBundle\Tests\ProjectVersionTrait; use Symfony\Component\HttpFoundation\Request; class FilterOperatorSubscriberTest extends MauticMysqlTestCase { - public function testIfNewOperatorNotInCustomObjectsAddedinSegmentFilter() - { - // Create a segment - $segment = new LeadList(); - $segment->setName('Test Segment A'); - $segment->setPublicName('Test Segment A'); - $segment->setAlias('test-segment-a'); + use ProjectVersionTrait; - $this->em->persist($segment); - $this->em->flush(); + /** + * @var CommandHelper + */ + private $commandHelper; - $crawler = $this->client->request(Request::METHOD_GET, '/s/segments/edit/'.$segment->getId()); + protected function setUp(): void + { + parent::setUp(); + $this->commandHelper = static::getContainer()->get('mautic.helper.command'); + } + public function testIfNewOperatorNotInCustomObjectsAddedinSegmentFilter() + { + $crawler = $this->client->request(Request::METHOD_GET, '/s/segments/new/'); $segment_filters = $crawler->filter('#available_segment_filters')->html(); - $this->assertStringContainsString('not in custom objects', $segment_filters); } @@ -62,17 +70,17 @@ public function testIfProperContactsAreAddedinSegmentWithNotInCustomObjectsFilte // 3) create a segment with filter : email > not in custom objects > select custom object $filters = [[ - 'object' => 'lead', - 'glue' => 'and', - 'field' => 'email', - 'type' => 'text', - 'operator' => 'notInCustomObjects', - 'properties' => [ - 'filter' => 'custom-object:'.$customObject->getId().':name', - ], - 'filter' => 'custom-object:'.$customObject->getId().':name', - 'display' => null, - ]]; + 'object' => 'lead', + 'glue' => 'and', + 'field' => 'email', + 'type' => 'text', + 'operator' => 'notInCustomObjects', + 'properties' => [ + 'filter' => 'custom-object:'.$customObject->getId().':name', + ], + 'filter' => 'custom-object:'.$customObject->getId().':name', + 'display' => null, + ]]; $segment = new LeadList(); $segment->setName('Test Segment A'); $segment->setPublicName('Test Segment A'); @@ -82,7 +90,7 @@ public function testIfProperContactsAreAddedinSegmentWithNotInCustomObjectsFilte $this->em->flush(); // 4) run update segment command - $this->runCommand('mautic:segments:update', ['-i' => $segment->getId()]); + $this->commandHelper->runCommand('mautic:segments:update', ['-i' => $segment->getId()]); // 5) fetch segment added contacts $leads = $this->em->getRepository(ListLead::class)->findBy(['list' => $segment->getId()], ['lead' => 'DESC']); @@ -94,4 +102,69 @@ public function testIfProperContactsAreAddedinSegmentWithNotInCustomObjectsFilte $this->assertSame($contact2->getLastname(), $leads[0]->getLead()->getLastname()); $this->assertSame($contact2->getEmail(), $leads[0]->getLead()->getEmail()); } + + public function testCustomObjectSegmentFilterOperatorForDateField(): void + { + if (!$this->isCloudProject()) { + $this->markTestSkipped('As context is not available for segment only in 4.4'); + } + + $leadField = $this->createField('date_field', 'date'); + + $fieldTypeProvider = self::$container->get('custom_field.type.provider'); + \assert($fieldTypeProvider instanceof CustomFieldTypeProvider); + $objectType = $fieldTypeProvider->getType('date'); + $dateField = $this->createCustomField('co_date_field', $objectType); + + $this->createCustomObject('obj', $dateField); + + $this->em->flush(); + $crawler = $this->client->request(Request::METHOD_GET, '/s/segments/new/'); + + $coDateFilterOperators = $crawler + ->filter('#available_segment_filters option[id="available_custom_object_cmf_'.$dateField->getId().'"]') + ->attr('data-field-operators'); + + $leadDateFilterOperators = $crawler + ->filter('#available_segment_filters option[id="available_lead_'.$leadField->getAlias().'"]') + ->attr('data-field-operators'); + + $this->assertSame($coDateFilterOperators, $leadDateFilterOperators); + } + + private function createField(string $alias, string $type): LeadField + { + $field = new LeadField(); + $field->setName($alias); + $field->setAlias($alias); + $field->setType($type); + $this->em->persist($field); + + return $field; + } + + private function createCustomObject(string $alias, ?CustomField $dateField = null): CustomObject + { + $customObject = new CustomObject(); + $customObject->setNameSingular($alias); + $customObject->setNamePlural($alias.'s'); + $customObject->setAlias($alias); + if ($dateField) { + $customObject->addCustomField($dateField); + } + $this->em->persist($customObject); + + return $customObject; + } + + private function createCustomField(string $alias, CustomFieldTypeInterface $objectType): CustomField + { + $dateField = new CustomField(); + $dateField->setTypeObject($objectType); + $dateField->setType($objectType->getKey()); + $dateField->setLabel($alias); + $dateField->setAlias($alias); + + return $dateField; + } } diff --git a/Tests/Functional/EventListener/ImportSubscriberTest.php b/Tests/Functional/EventListener/ImportSubscriberTest.php index 4d3d50278..22bafbb59 100644 --- a/Tests/Functional/EventListener/ImportSubscriberTest.php +++ b/Tests/Functional/EventListener/ImportSubscriberTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Functional\EventListener; -use DateTimeImmutable; use Mautic\CoreBundle\Test\MauticMysqlTestCase; use Mautic\LeadBundle\Entity\Import; use Mautic\LeadBundle\Entity\Lead; @@ -24,7 +23,7 @@ use MauticPlugin\CustomObjectsBundle\Repository\CustomFieldRepository; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository; use MauticPlugin\CustomObjectsBundle\Tests\Functional\DataFixtures\Traits\CustomObjectsTrait; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ImportSubscriberTest extends MauticMysqlTestCase { @@ -62,8 +61,8 @@ public function testImportForAllFieldTypesWithValidValuesAndLinksPlusUpdateToo() ]; $expectedValues = $csvRow; - $expectedValues['datetime'] = new DateTimeImmutable('2019-03-04 12:35:09'); - $expectedValues['date'] = new DateTimeImmutable('2019-03-04 00:00:00'); + $expectedValues['datetime'] = new \DateTimeImmutable('2019-03-04 12:35:09'); + $expectedValues['date'] = new \DateTimeImmutable('2019-03-04 00:00:00'); $expectedValues['multiselect'] = ['option_b', 'option_a']; // Import the custom item @@ -100,8 +99,8 @@ public function testImportForAllFieldTypesWithValidValuesAndLinksPlusUpdateToo() $updateStatus = $this->importCsvRow($customObject, $editCsvRow); $expectedUpdatedValues = $editCsvRow; - $expectedUpdatedValues['datetime'] = new DateTimeImmutable('2019-03-04 12:35:09'); - $expectedUpdatedValues['date'] = new DateTimeImmutable('2019-05-24 00:00:00'); + $expectedUpdatedValues['datetime'] = new \DateTimeImmutable('2019-03-04 12:35:09'); + $expectedUpdatedValues['date'] = new \DateTimeImmutable('2019-05-24 00:00:00'); $expectedUpdatedValues['multiselect'] = ['option_b', 'option_a']; $this->assertTrue($updateStatus); @@ -167,8 +166,8 @@ public function testImportWithDefaultValues(): void ]; $expectedValues = $csvRow; - $expectedValues['datetime'] = new DateTimeImmutable('2019-03-04 12:35:09'); - $expectedValues['date'] = new DateTimeImmutable('2019-06-21 00:00:00'); + $expectedValues['datetime'] = new \DateTimeImmutable('2019-03-04 12:35:09'); + $expectedValues['date'] = new \DateTimeImmutable('2019-06-21 00:00:00'); $expectedValues['multiselect'] = ['option_b']; $expectedValues['text'] = 'A default value'; diff --git a/Tests/Functional/EventListener/TokenSubscriberTest.php b/Tests/Functional/EventListener/TokenSubscriberTest.php index 82b0de65f..e70afafaf 100644 --- a/Tests/Functional/EventListener/TokenSubscriberTest.php +++ b/Tests/Functional/EventListener/TokenSubscriberTest.php @@ -17,6 +17,7 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Tests\Functional\DataFixtures\Traits\CustomObjectsTrait; +#[\AllowDynamicProperties] class TokenSubscriberTest extends MauticMysqlTestCase { use CustomObjectsTrait; diff --git a/Tests/Functional/Helper/QueryFilterHelperTest.php b/Tests/Functional/Helper/QueryFilterHelperTest.php index ee61f389c..c890f4183 100644 --- a/Tests/Functional/Helper/QueryFilterHelperTest.php +++ b/Tests/Functional/Helper/QueryFilterHelperTest.php @@ -7,6 +7,7 @@ use Mautic\CoreBundle\Test\MauticMysqlTestCase; use Mautic\LeadBundle\Segment\ContactSegmentFilterFactory; use Mautic\LeadBundle\Segment\Query\QueryBuilder; +use Mautic\LeadBundle\Segment\RandomParameterName; use MauticPlugin\CustomObjectsBundle\Helper\QueryFilterFactory; use MauticPlugin\CustomObjectsBundle\Helper\QueryFilterHelper; use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider; @@ -46,7 +47,8 @@ protected function setUp(): void $customFieldRepository, new QueryFilterFactory\Calculator(), 1 - ) + ), + new RandomParameterName() ); $fixturesDirectory = $this->getFixturesDirectory(); @@ -65,7 +67,7 @@ protected function setUp(): void public function testGetCustomValueValueExpression(): void { $this->assertMatchWhere( - 'test_value.value = :test_value_value', + 'test_value.value = :par0', [ 'glue' => 'and', 'field' => 'cmf_'.$this->getFixtureById('custom_field1')->getId(), @@ -76,18 +78,22 @@ public function testGetCustomValueValueExpression(): void ); $this->assertMatchWhere( - 'test_value.value LIKE :test_value_value', + 'test_value.value LIKE :par1', [ - 'glue' => 'and', - 'field' => 'cmf_'.$this->getFixtureById('custom_field1')->getId(), - 'type' => 'custom_object', - 'operator' => 'like', - 'value' => 'love', + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_field1')->getId(), + 'type' => 'custom_object', + 'operator' => 'like', + 'value' => 'love', + 'filter' => '500', + 'properties' => [ + 'filter' => '500', + ], ] ); $this->assertMatchWhere( - '(test_value.value <> :test_value_value) OR (test_value.value IS NULL)', + '(test_value.value <> :par2) OR (test_value.value IS NULL)', [ 'glue' => 'and', 'field' => 'cmf_'.$this->getFixtureById('custom_field1')->getId(), @@ -98,21 +104,190 @@ public function testGetCustomValueValueExpression(): void ); $this->assertMatchWhere( - 'test_value.value > :test_value_value', + 'test_value.value > :par3', [ 'glue' => 'and', 'field' => 'cmf_'.$this->getFixtureById('custom_object_product')->getId(), 'object' => 'custom_object', 'type' => 'int', 'operator' => 'gt', + 'filter' => '500', 'properties' => [ 'filter' => '500', ], ] ); + + $this->assertMatchWhere( + "test_value.value BETWEEN '2024-05-15 00:00:00' AND '2024-05-24 23:59:59'", + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_object_product')->getId(), + 'object' => 'custom_object', + 'type' => 'datetime', + 'operator' => 'between', + 'properties' => [ + 'filter' => [ + 'date_from' => 'May 15, 2024', + 'date_to' => 'May 24, 2024', + ], + ], + ] + ); + + $this->assertMatchWhere( + 'test_value.value LIKE :par5', + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_field1')->getId(), + 'object' => 'custom_object', + 'type' => 'datetime', + 'operator' => 'like', + 'properties' => [ + 'filter' => '2024', + ], + ] + ); + + $this->assertMatchWhere( + 'test_value.value REGEXP :par6', + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_field1')->getId(), + 'object' => 'custom_object', + 'type' => 'datetime', + 'operator' => 'regexp', + 'properties' => [ + 'filter' => '2024', + ], + ] + ); + + $this->assertMatchWhere( + 'test_value.value LIKE :par7', + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_field1')->getId(), + 'object' => 'custom_object', + 'type' => 'datetime', + 'operator' => 'startsWith', + 'properties' => [ + 'filter' => '2024', + ], + ] + ); + + $this->assertMatchWhere( + 'test_value.value LIKE :par8', + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_field1')->getId(), + 'object' => 'custom_object', + 'type' => 'datetime', + 'operator' => 'endsWith', + 'properties' => [ + 'filter' => '2024', + ], + ] + ); + + $this->assertMatchWhere( + 'test_value.value LIKE :par9', + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_field1')->getId(), + 'object' => 'custom_object', + 'type' => 'datetime', + 'operator' => 'contains', + 'properties' => [ + 'filter' => '2024', + ], + ] + ); + + $this->assertMatchWhere( + 'test_value.value IS NULL', + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_object_product')->getId(), + 'object' => 'custom_object', + 'type' => 'datetime', + 'operator' => 'empty', + 'properties' => [ + 'filter' => [], + ], + ] + ); + + $this->assertMatchWhere( + 'test_value.value IS NOT NULL', + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_object_product')->getId(), + 'object' => 'custom_object', + 'type' => 'datetime', + 'operator' => '!empty', + 'properties' => [ + 'filter' => [], + ], + ] + ); + + $this->assertMatchWhere( + 'test_value.value BETWEEN 0 AND 10', + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_object_product')->getId(), + 'object' => 'custom_object', + 'type' => 'int', + 'operator' => 'between', + 'properties' => [ + 'filter' => [ + 'number_from' => 0, + 'number_to' => 10, + ], + ], + ] + ); + + $this->assertMatchWhere( + 'test_value.value >= :pard', + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_object_product')->getId(), + 'object' => 'custom_object', + 'type' => 'date', + 'operator' => 'gte', + 'properties' => [ + 'filter' => [ + 'dateTypeMode' => 'absolute', + 'absoluteDate' => 'yesterday', + ], + ], + ], + (new \DateTime('yesterday'))->format('Y-m-d') + ); + + $this->assertMatchWhere( + 'test_value.value <= :pare', + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->getFixtureById('custom_object_product')->getId(), + 'object' => 'custom_object', + 'type' => 'datetime', + 'operator' => 'lte', + 'properties' => [ + 'filter' => [ + 'dateTypeMode' => 'absolute', + 'absoluteDate' => 'tomorrow', + ], + ], + ], + (new \DateTime('tomorrow'))->format('Y-m-d 23:59:59') + ); } - protected function assertMatchWhere(string $expectedWhere, array $filter): void + protected function assertMatchWhere(string $expectedWhere, array $filter, ?string $expectedValue = null): void { $unionQueryContainer = new UnionQueryContainer(); $qb = new QueryBuilder($this->em->getConnection()); @@ -125,7 +300,12 @@ protected function assertMatchWhere(string $expectedWhere, array $filter): void ); $unionQueryContainer->rewind(); + $whereResponse = (string) $unionQueryContainer->current()->getQueryPart('where'); + $this->assertSame($expectedWhere, $whereResponse); + if ($expectedValue) { + $this->assertSame($expectedValue, current($unionQueryContainer->current()->getParameters())); + } } } diff --git a/Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php b/Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php index 3c501e52d..f94a020d5 100644 --- a/Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php +++ b/Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php @@ -6,6 +6,7 @@ use Mautic\CoreBundle\Test\MauticMysqlTestCase; use Mautic\LeadBundle\Segment\ContactSegmentFilter; +use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate; use Mautic\LeadBundle\Segment\Query\QueryBuilder; use Mautic\LeadBundle\Segment\RandomParameterName; use MauticPlugin\CustomObjectsBundle\Helper\QueryFilterFactory; @@ -24,6 +25,12 @@ class CustomFieldFilterQueryBuilderTest extends MauticMysqlTestCase use FixtureObjectsTrait; use DbalQueryTrait; + protected function setUp(): void + { + $this->configParams['custom_object_merge_filter'] = false; + parent::setUp(); + } + public function testApplyQuery(): void { $fixturesDirectory = $this->getFixturesDirectory(); @@ -54,7 +61,8 @@ public function testApplyQuery(): void $customFieldRepository, new QueryFilterFactory\Calculator(), 1 - ) + ), + new RandomParameterName() ); $queryBuilderService = new CustomFieldFilterQueryBuilder( new RandomParameterName(), @@ -91,12 +99,13 @@ private function createSegmentFilterMock( $filterMock = $this->getMockBuilder(ContactSegmentFilter::class) ->disableOriginalConstructor() ->getMock(); - + $filterMock->contactSegmentFilterCrate = $this->createMock(ContactSegmentFilterCrate::class); $filterMock->method('getType')->willReturn($type); $filterMock->method('getOperator')->willReturn($operator); $filterMock->method('getField')->willReturn((string) $this->getFixtureById($fixtureField)->getId()); $filterMock->method('getParameterValue')->willReturn($value); $filterMock->method('getParameterHolder')->willReturn((string) ':needle'); + $filterMock->method('getGlue')->willReturn($operator); return $filterMock; } diff --git a/Tests/Functional/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php b/Tests/Functional/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php index 2de0bf6a6..666f9409b 100644 --- a/Tests/Functional/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php +++ b/Tests/Functional/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php @@ -59,7 +59,8 @@ public function testApplyQuery(): void $customFieldRepository, new QueryFilterFactory\Calculator(), 1 - ) + ), + new RandomParameterName() ); $queryBuilderService = new CustomItemNameFilterQueryBuilder( new RandomParameterName(), @@ -94,6 +95,7 @@ private function createSegmentFilterMock($value, $type = 'text', $operator = 'eq $filterMock->method('getField')->willReturn((string) $this->getFixtureById($fixtureField)->getId()); $filterMock->method('getParameterValue')->willReturn($value); $filterMock->method('getParameterHolder')->willReturn((string) ':needle'); + $filterMock->method('getGlue')->willReturn($operator); return $filterMock; } diff --git a/Tests/Functional/Segment/Query/Filter/CustomItemRelationQueryBuilderTestCase.php b/Tests/Functional/Segment/Query/Filter/CustomItemRelationQueryBuilderTest.php similarity index 91% rename from Tests/Functional/Segment/Query/Filter/CustomItemRelationQueryBuilderTestCase.php rename to Tests/Functional/Segment/Query/Filter/CustomItemRelationQueryBuilderTest.php index 2f9bdd452..50c4b66bc 100644 --- a/Tests/Functional/Segment/Query/Filter/CustomItemRelationQueryBuilderTestCase.php +++ b/Tests/Functional/Segment/Query/Filter/CustomItemRelationQueryBuilderTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Functional\Segment\Query\Filter; -use InvalidArgumentException; use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Test\MauticMysqlTestCase; use Mautic\LeadBundle\Entity\LeadList; @@ -13,24 +12,13 @@ use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; use MauticPlugin\CustomObjectsBundle\Tests\Functional\DataFixtures\Traits\FixtureObjectsTrait; -class CustomItemRelationQueryBuilderTestCase extends MauticMysqlTestCase +class CustomItemRelationQueryBuilderTest extends MauticMysqlTestCase { use FixtureObjectsTrait; - /** - * @var CoreParametersHelper - */ - private $coreParametersHelper; - - /** - * @var LeadListRepository - */ - private $segmentRepository; - - /** - * @var LeadRepository - */ - private $contactRepository; + private CoreParametersHelper $coreParametersHelper; + private LeadListRepository $segmentRepository; + private LeadRepository $contactRepository; protected function setUp(): void { @@ -173,11 +161,12 @@ private function assertLeadCountBySegmentAlias(int $expectedLeadCount, string $s $segment = $this->segmentRepository->findOneBy(['alias' => $segmentAlias]); if (!$segment) { - throw new InvalidArgumentException("No segment with alias '{$segmentAlias}' found"); + throw new \InvalidArgumentException("No segment with alias '{$segmentAlias}' found"); } - $count = $this->segmentRepository->getLeadCount([$segment->getId()]); - $count = (int) $count[$segment->getId()]; + $count = $this->segmentRepository->getLeadCount($segment->getId()); + $this->assertIsNumeric($count); + $count = (int) $count; $this->assertSame( $expectedLeadCount, @@ -188,7 +177,7 @@ private function assertLeadCountBySegmentAlias(int $expectedLeadCount, string $s private function assertContactIsInSegment(string $contactEmail, string $segmentAlias): void { - $contact = $this->contactRepository->findOneByEmail($contactEmail); + $contact = $this->contactRepository->findOneBy(['email' => $contactEmail]); /** @var LeadList[] $segments */ $segments = $this->segmentRepository->getLeadLists($contact->getId()); diff --git a/Tests/Functional/Segment/Query/Filter/CustomObjectMergedFilterQueryBuilderTest.php b/Tests/Functional/Segment/Query/Filter/CustomObjectMergedFilterQueryBuilderTest.php new file mode 100644 index 000000000..ab051ccb7 --- /dev/null +++ b/Tests/Functional/Segment/Query/Filter/CustomObjectMergedFilterQueryBuilderTest.php @@ -0,0 +1,122 @@ +configParams['custom_object_merge_filter'] = true; + $this->configParams[ConfigProvider::CONFIG_PARAM_ITEM_VALUE_TO_CONTACT_RELATION_LIMIT] = 0; + parent::setUp(); + } + + public function testMergedSegmentFilters(): void + { + $fixturesDirectory = $this->getFixturesDirectory(); + $objects = $this->loadFixtureFiles([ + $fixturesDirectory.'/leads.yml', + $fixturesDirectory.'/custom_objects.yml', + $fixturesDirectory.'/custom_fields.yml', + $fixturesDirectory.'/custom_items.yml', + $fixturesDirectory.'/custom_xref.yml', + $fixturesDirectory.'/custom_values.yml', + ]); + $this->setFixtureObjects($objects); + + $customField = $this->getFixtureById('custom_field1')->getId(); + + $filters = [ + [ + 'glue' => 'and', + 'object' => 'custom_object', + 'type' => 'text', + 'field' => 'cmf_'.$customField, + 'properties' => ['filter' => 'l'], + 'operator' => 'startsWith', + ], + [ + 'glue' => 'and', + 'object' => 'custom_object', + 'type' => 'text', + 'field' => 'cmf_'.$customField, + 'properties' => ['filter' => 'e'], + 'operator' => 'endsWith', + ], + [ + 'object' => 'custom_object', + 'glue' => 'and', + 'field' => 'cmf_'.$customField, + 'type' => 'text', + 'operator' => '!=', + 'properties' => ['filter' => 'some random text'], + 'filter' => 'some random text', + 'display' => null, + ], + ]; + $segment = $this->createSegment($filters); + + $applicationTester = $this->testSymfonyCommand('mautic:segments:update', ['-i' => $segment->getId(), '--env' => 'test']); + Assert::assertSame(0, $applicationTester->getStatusCode()); + Assert::assertStringContainsString('3 total contact(s) to be added in batches of 300', $applicationTester->getDisplay()); + } + + public function testMergedSegmentSingleFilter(): void + { + $fixturesDirectory = $this->getFixturesDirectory(); + $objects = $this->loadFixtureFiles([ + $fixturesDirectory.'/leads.yml', + $fixturesDirectory.'/custom_objects.yml', + $fixturesDirectory.'/custom_fields.yml', + $fixturesDirectory.'/custom_items.yml', + $fixturesDirectory.'/custom_xref.yml', + $fixturesDirectory.'/custom_values.yml', + ]); + $this->setFixtureObjects($objects); + + $customField = $this->getFixtureById('custom_field1')->getId(); + + $filters = [ + [ + 'object' => 'custom_object', + 'glue' => 'and', + 'field' => 'cmf_'.$customField, + 'type' => 'text', + 'operator' => '=', + 'properties' => ['filter' => 'love'], + 'filter' => 'some random text', + 'display' => null, + ], + ]; + $segment = $this->createSegment($filters); + + $applicationTester = $this->testSymfonyCommand('mautic:segments:update', ['-i' => $segment->getId(), '--env' => 'test']); + Assert::assertSame(0, $applicationTester->getStatusCode()); + Assert::assertStringContainsString('3 total contact(s) to be added in batches of 300', $applicationTester->getDisplay()); + } + + /** + * @param mixed[] $filters + */ + private function createSegment(array $filters): LeadList + { + $segment = new LeadList(); + $segment->setFilters($filters); + $segment->setName('Segment A'); + $segment->setAlias('segment-a'); + $this->em->persist($segment); + $this->em->flush(); + + return $segment; + } +} diff --git a/Tests/Functional/Segment/Query/Filter/NegativeOperatorFilterQueryBuilderTest.php b/Tests/Functional/Segment/Query/Filter/NegativeOperatorFilterQueryBuilderTest.php new file mode 100644 index 000000000..06ab327ec --- /dev/null +++ b/Tests/Functional/Segment/Query/Filter/NegativeOperatorFilterQueryBuilderTest.php @@ -0,0 +1,205 @@ +getDataSetAsString(false); + + if ($mergeFilterEnabled && !method_exists(ContactSegmentFilterCrate::class, 'getMergedProperty')) { + $this->markTestSkipped(); + } + + $this->configParams['custom_object_merge_filter'] = $mergeFilterEnabled; + $this->configParams['custom_object_item_value_to_contact_relation_limit'] = $mergeFilterEnabled ? 0 : 3; + + parent::setUp(); + + $this->customItemModel = self::$container->get('mautic.custom.model.item'); + $this->createCustomObjectWithCustomField(); + $this->em->flush(); + } + + /** + * @return iterable + */ + public function dataUseMergeFilter(): iterable + { + yield 'Merge filter enabled' => [true]; + yield 'Merge filter disabled' => [false]; + } + + /** + * @dataProvider dataUseMergeFilter + */ + public function testNotEqualsOperator(bool $mergeFilterEnabled): void + { + $this->createContactAndAttachCustomItem('abc', 'ABC'); + $this->createContactAndAttachCustomItem('xyz', 'XYZ'); + $this->createContactAndAttachCustomItem('empty', ''); + $this->createContact('unlinked'); + + $segment = $this->createAndBuildSegment($this->createFilter('!=', 'abc')); + + $members = $this->em->getRepository(ListLead::class)->findBy(['list' => $segment]); + Assert::assertCount($mergeFilterEnabled ? 2 : 3, $members); + + $firstnames = $this->extractFirstnamesFromSegmentMembers($members); + Assert::assertNotContains('abc', $firstnames); + Assert::assertContains('xyz', $firstnames); + Assert::assertContains('empty', $firstnames); + + if ($mergeFilterEnabled) { + Assert::assertNotContains('unlinked', $firstnames); + } else { + Assert::assertContains('unlinked', $firstnames); + } + } + + /** + * @dataProvider dataUseMergeFilter + */ + public function testEmptyOperator(bool $mergeFilterEnabled): void + { + $this->createContactAndAttachCustomItem('not empty', 'Not empty'); + $this->createContactAndAttachCustomItem('empty', ''); + $this->createContact('unlinked 1'); + $this->createContact('unlinked 2'); + + $segment = $this->createAndBuildSegment($this->createFilter('empty', null)); + + $members = $this->em->getRepository(ListLead::class)->findBy(['list' => $segment]); + Assert::assertCount($mergeFilterEnabled ? 1 : 3, $members); + + $firstnames = $this->extractFirstnamesFromSegmentMembers($members); + Assert::assertNotContains('not empty', $firstnames); + Assert::assertContains('empty', $firstnames); + + if ($mergeFilterEnabled) { + Assert::assertNotContains('unlinked 1', $firstnames); + Assert::assertNotContains('unlinked 2', $firstnames); + } else { + Assert::assertContains('unlinked 1', $firstnames); + Assert::assertContains('unlinked 2', $firstnames); + } + } + + private function createCustomItem(CustomObject $customObject, string $value, string $name): CustomItem + { + $customItem = new CustomItem($customObject); + $customFieldValue = new CustomFieldValueText($this->customField, $customItem, $value); + $customItem->addCustomFieldValue($customFieldValue); + $customItem->setName($name); + $this->em->persist($customItem); + $this->em->persist($customFieldValue); + + return $customItem; + } + + private function createCustomObjectWithCustomField(): void + { + $this->customField = new CustomField(); + $this->customField->setLabel('Field'); + $this->customField->setAlias('field'); + $this->customField->setType('text'); + $this->em->persist($this->customField); + + $this->customObject = new CustomObject(); + $this->customObject->setAlias('Object'); + $this->customObject->setNameSingular('Object'); + $this->customObject->setNamePlural('Objects'); + $this->customObject->addCustomField($this->customField); + $this->customField->setCustomObject($this->customObject); + $this->em->persist($this->customObject); + } + + /** + * @param array $filters + */ + private function createAndBuildSegment(array $filters): LeadList + { + $segment = new LeadList(); + $segment->setName('Segment A'); + $segment->setPublicName('Segment A'); + $segment->setAlias('segment-a'); + $segment->setFilters($filters); + $this->em->persist($segment); + $this->em->flush($segment); + $this->em->clear(); + + $commandTester = $this->testSymfonyCommand(UpdateLeadListsCommand::NAME, ['-i' => $segment->getId()]); + Assert::assertSame(0, $commandTester->getStatusCode(), 'Update lead lists command was not successful'); + + return $segment; + } + + private function createContact(string $firstname): Lead + { + $contact = new Lead(); + $contact->setFirstname($firstname); + $this->em->persist($contact); + + return $contact; + } + + private function createContactAndAttachCustomItem(string $contactFirstname, string $customItemText): void + { + $contact = $this->createContact($contactFirstname); + $this->em->flush(); + + $customItem = $this->createCustomItem($this->customObject, $customItemText, $customItemText); + $this->customItemModel->linkEntity($customItem, 'contact', (int) $contact->getId()); + } + + /** + * @return array + */ + private function createFilter(string $operator, ?string $value): array + { + $filters = [ + [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->customField->getId(), + 'object' => 'custom_object', + 'type' => 'text', + 'operator' => $operator, + 'properties' => [ + 'filter' => $value, + ], + ], + ]; + + return $filters; + } + + /** + * @param array $members + * + * @return array + */ + private function extractFirstnamesFromSegmentMembers(array $members): array + { + return array_map(fn (ListLead $segment) => $segment->getLead()->getFirstname(), $members); + } +} diff --git a/Tests/Functional/Token/EmailTokenTest.php b/Tests/Functional/Token/EmailTokenTest.php index cc6437161..84b7e5297 100644 --- a/Tests/Functional/Token/EmailTokenTest.php +++ b/Tests/Functional/Token/EmailTokenTest.php @@ -16,6 +16,7 @@ use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\HttpFoundation\Request; +#[\AllowDynamicProperties] class EmailTokenTest extends MauticMysqlTestCase { use CustomObjectsTrait; diff --git a/Tests/Functional/Token/EmailWithCustomObjectDynamicContentFunctionalTest.php b/Tests/Functional/Token/EmailWithCustomObjectDynamicContentFunctionalTest.php new file mode 100644 index 000000000..606948748 --- /dev/null +++ b/Tests/Functional/Token/EmailWithCustomObjectDynamicContentFunctionalTest.php @@ -0,0 +1,339 @@ + + */ + private $customItems; + + /** + * @var array + */ + private $customFieldValues; + + protected function setUp(): void + { + parent::setUp(); + + $this->customItemModel = self::$container->get('mautic.custom.model.item'); + $this->customFieldValueModel = self::$container->get('mautic.custom.model.field.value'); + + $this->customObject = $this->createCustomObjectWithAllFields(self::$container, 'Car'); + $this->customItems['nexon'] = new CustomItem($this->customObject); + + $this->customItems['nexon']->setName('Nexon'); + $this->customFieldValueModel->createValuesForItem($this->customItems['nexon']); + + $this->customFieldValues['nexon-text'] = $this->customItems['nexon']->findCustomFieldValueForFieldAlias('text-test-field'); + $this->customFieldValues['nexon-text']->setValue('Tata'); + + $this->customFieldValues['nexon-datetime'] = $this->customItems['nexon']->findCustomFieldValueForFieldAlias('datetime-test-field'); + $this->customFieldValues['nexon-datetime']->setValue('2024-07-01 13:29:43'); + + $this->customFieldValues['nexon-multiselect'] = $this->customItems['nexon']->findCustomFieldValueForFieldAlias('multiselect-test-field'); + $this->customFieldValues['nexon-multiselect']->setValue('option_a'); + + $this->customFieldValues['nexon-select'] = $this->customItems['nexon']->findCustomFieldValueForFieldAlias('select-test-field'); + + $this->customFieldValues['nexon-url'] = $this->customItems['nexon']->findCustomFieldValueForFieldAlias('url-test-field'); + $this->customFieldValues['nexon-url']->setValue('https://test.mautic.fr'); + + $this->customFieldValues['nexon-number'] = $this->customItems['nexon']->findCustomFieldValueForFieldAlias('number-test-field'); + $this->customFieldValues['nexon-number']->setValue(10); + + $this->customItems['nexon'] = $this->customItemModel->save($this->customItems['nexon']); + + $this->customItems['fortuner'] = new CustomItem($this->customObject); + + $this->customItems['fortuner']->setName('Fortuner'); + $this->customFieldValueModel->createValuesForItem($this->customItems['fortuner']); + + $this->customFieldValues['fortuner-text'] = $this->customItems['fortuner']->findCustomFieldValueForFieldAlias('text-test-field'); + $this->customFieldValues['fortuner-text']->setValue('Toyota'); + + $this->customItems['fortuner'] = $this->customItemModel->save($this->customItems['fortuner']); + + $this->customItems['city'] = new CustomItem($this->customObject); + + $this->customItems['city']->setName('City'); + $this->customFieldValueModel->createValuesForItem($this->customItems['city']); + + $this->customFieldValues['city-text'] = $this->customItems['city']->findCustomFieldValueForFieldAlias('text-test-field'); + $this->customFieldValues['city-text']->setValue('Honda'); + + $this->customItems['city'] = $this->customItemModel->save($this->customItems['city']); + } + + public function testDynamicContentEmail(): void + { + foreach ([ + [ + 'nexonlikeurl@acquia.com', + $this->buildDynamicContentArray([ + ['nexon-url', 'tic.f', 'like'], + ]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonselect@acquia.com', + $this->buildDynamicContentArray([ + ['nexon-select', null, 'empty', 'select'], + ]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonmultiselect@acquia.com', + $this->buildDynamicContentArray([ + ['nexon-datetime', null, '!empty', 'datetime'], + ['nexon-number', 12, 'lt', 'number'], + ]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonmultiselect@acquia.com', + $this->buildDynamicContentArray([ + ['nexon-text', 'Tata', '='], + ['nexon-datetime', '2024-07-01 00:00', 'gte', 'datetime'], + ['nexon-multiselect', 'option_a', 'in', 'multiselect'], + ]), + 'Custom Object Dynamic Content', + ], + [ + 'nexondatetime@acquia.com', + $this->buildDynamicContentArray([ + ['nexon-text', 'Tata', '='], + ['nexon-datetime', '2024-07-01', 'gte'], + ]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonequal@acquia.com', + $this->buildDynamicContentArray([ + ['nexon-text', 'Tata', '='], + ]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonnotequal@acquia.com', + $this->buildDynamicContentArray([['nexon-text', 'Toyota', '!=']]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonempty@acquia.com', + $this->buildDynamicContentArray([['nexon-text', '', 'empty']]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonnotempty@acquia.com', + $this->buildDynamicContentArray([['nexon-text', '', '!empty']]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonlike@acquia.com', + $this->buildDynamicContentArray([['nexon-text', 'at', 'like']]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonnotlike@acquia.com', + $this->buildDynamicContentArray([['nexon-text', 'Toyota', '!like']]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonstartsWith@acquia.com', + $this->buildDynamicContentArray([['nexon-text', 'Ta', 'startsWith']]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonendsWith@acquia.com', + $this->buildDynamicContentArray([['nexon-text', 'ta', 'endsWith']]), + 'Custom Object Dynamic Content', + ], + [ + 'nexonendsWith@acquia.com', + $this->buildDynamicContentArray([['nexon-text', 'at', 'contains']]), + 'Custom Object Dynamic Content', + ], + ] as $item) { + $this->emailWithCustomObjectDynamicContent($item[0], $item[1], $item[2]); + } + } + + /** + * @param array $inputs + * + * @return array + */ + private function buildDynamicContentArray(array $inputs): array + { + return [ + [ + 'tokenName' => 'Dynamic Content 1', + 'content' => 'Default Dynamic Content', + 'filters' => [ + [ + 'content' => null, + 'filters' => [ + ], + ], + ], + ], + [ + 'tokenName' => 'Dynamic Content 2', + 'content' => 'Default Dynamic Content', + 'filters' => [ + [ + 'content' => 'Custom Object Dynamic Content', + 'filters' => array_merge( + array_map(function ($input) { + return [ + 'glue' => 'and', + 'field' => 'cmf_'.$this->customFieldValues[$input[0]]->getCustomField()->getId(), + 'object' => 'custom_object', + 'type' => $input[3] ?? 'text', + 'filter' => $input[1], + 'display' => $this->customObject->getName().':'.$this->customFieldValues[$input[0]]->getCustomField()->getLabel(), + 'operator' => $input[2], + ]; + }, $inputs), + [ + [ + 'glue' => 'and', + 'field' => 'email', + 'object' => 'lead', + 'type' => 'email', + 'filter' => null, + 'operator' => '!empty', + ], + ] + ), + ], + ], + ], + ]; + } + + /** + * @param array $dynamicContent + */ + private function emailWithCustomObjectDynamicContent(string $emailAddress, array $dynamicContent, string $assertText): void + { + $lead = $this->createLead($emailAddress); + $email = $this->createEmail(); + $email->setDynamicContent($dynamicContent); + $this->em->persist($email); + $this->em->flush(); + + $this->customItemModel->linkEntity($this->customItems['nexon'], 'contact', (int) $lead->getId()); + $this->customItemModel->linkEntity($this->customItems['fortuner'], 'contact', (int) $lead->getId()); + $this->customItemModel->linkEntity($this->customItems['city'], 'contact', (int) $lead->getId()); + + $this->sendAndAssetText($email, $lead, $assertText); + } + + private function createEmail(bool $publicPreview = true): Email + { + $email = new Email(); + $email->setDateAdded(new \DateTime()); + $email->setName('Email name'); + $email->setSubject('Email subject'); + $email->setTemplate('Blank'); + $email->setPublicPreview($publicPreview); + $email->setCustomHtml('{dynamiccontent="Dynamic Content 2"}'); + $this->em->persist($email); + + return $email; + } + + private function createLead(string $email): Lead + { + $lead = new Lead(); + $lead->setEmail($email); + $this->em->persist($lead); + + return $lead; + } + + private function sendAndAssetText(Email $email, Lead $lead, string $matchText): void + { + /** @var EmailModel $emailModel */ + $emailModel = self::$container->get('mautic.email.model.email'); + $emailModel->sendEmail( + $email, + [ + [ + 'id' => $lead->getId(), + 'email' => $lead->getEmail(), + 'firstname' => $lead->getFirstname(), + 'lastname' => $lead->getLastname(), + ], + ] + ); + + /** @var StatRepository $emailStatRepository */ + $emailStatRepository = $this->em->getRepository(Stat::class); + + /** @var Stat|null $emailStat */ + $emailStat = $emailStatRepository->findOneBy( + [ + 'email' => $email->getId(), + 'lead' => $lead->getId(), + ] + ); + + Assert::assertNotNull($emailStat); + + $crawler = $this->client->request(Request::METHOD_GET, "/email/view/{$emailStat->getTrackingHash()}"); + + $body = $crawler->filter('body'); + + // Remove the tracking tags that are causing troubles with different Mautic configurations. + $body->filter('a,img,div')->each(function (Crawler $crawler) { + foreach ($crawler as $node) { + $node->parentNode->removeChild($node); + } + }); + + Assert::assertStringContainsString( + $matchText, + $body->html() + ); + } +} diff --git a/Tests/Functional/UpsertFunctionalTest.php b/Tests/Functional/UpsertFunctionalTest.php index a8ce1680e..34c0a6546 100644 --- a/Tests/Functional/UpsertFunctionalTest.php +++ b/Tests/Functional/UpsertFunctionalTest.php @@ -9,7 +9,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Tests\Functional\DataFixtures\Traits\CustomObjectsTrait; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class UpsertFunctionalTest extends \Mautic\CoreBundle\Test\MauticMysqlTestCase { diff --git a/Tests/ProjectVersionTrait.php b/Tests/ProjectVersionTrait.php new file mode 100644 index 000000000..9c8a22436 --- /dev/null +++ b/Tests/ProjectVersionTrait.php @@ -0,0 +1,13 @@ +enableProfiler(); + $this->client->enableProfiler(); $commandTester = $this->getCustomItemExportCommandTester(); $this->em->clear(); diff --git a/Tests/Unit/Controller/ControllerTestCase.php b/Tests/Unit/Controller/ControllerTestCase.php index 79e7520d1..59f678768 100644 --- a/Tests/Unit/Controller/ControllerTestCase.php +++ b/Tests/Unit/Controller/ControllerTestCase.php @@ -4,16 +4,19 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller; -use Mautic\CoreBundle\Controller\CommonController; -use Mautic\CoreBundle\Controller\MauticController; +use Doctrine\Persistence\ManagerRegistry; +use Mautic\CoreBundle\Factory\MauticFactory; use Mautic\CoreBundle\Factory\ModelFactory; use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Helper\UserHelper; use Mautic\CoreBundle\Model\NotificationModel; use Mautic\CoreBundle\Security\Permissions\CorePermissions; -use Mautic\CoreBundle\Templating\Engine\PhpEngine; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Mautic\CoreBundle\Service\FlashBag; +use Mautic\CoreBundle\Translation\Translator; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\HeaderBag; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; @@ -23,7 +26,6 @@ use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\Routing\Router; use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Translation\TranslatorInterface; use Twig\Environment; /** @@ -33,7 +35,6 @@ */ class ControllerTestCase extends \PHPUnit\Framework\TestCase { - protected $requestStack; protected $request; protected $session; @@ -48,43 +49,98 @@ class ControllerTestCase extends \PHPUnit\Framework\TestCase protected $container; /** - * @var UserHelper + * @var MockObject|UserHelper */ protected $userHelper; - protected function addSymfonyDependencies(Controller $controller): void + /** + * @var MockObject|ManagerRegistry + */ + protected $managerRegistry; + + /** + * @var MockObject|MauticFactory + */ + protected $mauticFactory; + + /** + * @var MockObject|ModelFactory + */ + protected $modelFactory; + + /** + * @var MockObject|CoreParametersHelper + */ + protected $coreParametersHelper; + + /** + * @var MockObject|EventDispatcherInterface + */ + protected $dispatcher; + + /** + * @var MockObject|Translator + */ + protected $translator; + + /** + * @var MockObject|FlashBag + */ + protected $flashBag; + + /** + * @var MockObject|RequestStack + */ + protected $requestStack; + + /** + * @var MockObject|CorePermissions + */ + protected $security; + + protected function setUp(): void + { + parent::setUp(); + + $this->security = $this->createMock(CorePermissions::class); + $this->userHelper = $this->createMock(UserHelper::class); + $this->container = $this->createMock(ContainerInterface::class); + $this->router = $this->createMock(RouterInterface::class); + $this->managerRegistry = $this->createMock(ManagerRegistry::class); + $this->mauticFactory = $this->createMock(MauticFactory::class); + $this->modelFactory = $this->createMock(ModelFactory::class); + $this->coreParametersHelper = $this->createMock(CoreParametersHelper::class); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->translator = $this->createMock(Translator::class); + $this->flashBag = $this->createMock(FlashBag::class); + $this->requestStack = $this->createMock(RequestStack::class); + $this->security = $this->createMock(CorePermissions::class); + } + + protected function addSymfonyDependencies(AbstractController $controller): void { $requestStack = empty($this->requestStack) ? $this->createMock(RequestStack::class) : $this->requestStack; $request = empty($this->request) ? $this->createMock(Request::class) : $this->request; $session = empty($this->session) ? $this->createMock(Session::class) : $this->session; + $modelFactory = empty($this->modelFactory) ? $this->createMock(ModelFactory::class) : $this->modelFactory; - $this->container = $this->createMock(ContainerInterface::class); $httpKernel = $this->createMock(HttpKernel::class); $response = $this->createMock(Response::class); - $phpEngine = $this->createMock(PhpEngine::class); - $modelFactory = $this->createMock(ModelFactory::class); + $twig = $this->createMock(Environment::class); $notificationModel = $this->createMock(NotificationModel::class); - $security = $this->createMock(CorePermissions::class); - $translator = $this->createMock(TranslatorInterface::class); - $this->router = $this->createMock(RouterInterface::class); - $this->userHelper = $this->createMock(UserHelper::class); $this->container->method('get')->willReturnMap([ ['request_stack', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $requestStack], ['http_kernel', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $httpKernel], - ['templating', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $phpEngine], ['mautic.model.factory', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $modelFactory], ['session', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $session], - ['mautic.security', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $security], + ['mautic.security', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->security], ['router', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->router], ['mautic.helper.user', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->userHelper], - ['twig', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $this->createMock(Environment::class)], + ['twig', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $twig], ]); - $phpEngine->method('renderResponse')->willReturn($response); - $this->container->method('has')->willReturnMap([ - ['templating', false], // 'templating' will be removed in Symfony 5 ['twig', true], ]); @@ -104,14 +160,5 @@ protected function addSymfonyDependencies(Controller $controller): void $requestStack->method('getCurrentRequest')->willReturn($request); $controller->setContainer($this->container); - - if ($controller instanceof MauticController) { - $controller->setRequest($request); - $controller->setTranslator($translator); - } - - if ($controller instanceof CommonController) { - $controller->setCoreParametersHelper($this->createMock(CoreParametersHelper::class)); - } } } diff --git a/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php b/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php index 404cc97d9..533cfb927 100644 --- a/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php +++ b/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php @@ -7,17 +7,18 @@ use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; abstract class AbstractFieldControllerTest extends ControllerTestCase { - protected function createRequestMock( + protected function createRequestStackMock( $objectId = null, $fieldId = null, $fieldType = null, $panelId = null, $panelCount = null, array $mapExtras = [] - ): Request { + ): RequestStack { $request = $this->createMock(Request::class); $map = [ @@ -39,8 +40,26 @@ protected function createRequestMock( $query = $this->createMock(ParameterBag::class); $query->method('get') ->willReturn($fieldId); + $query->method('all') + ->willReturn($map); $request->query = $query; - return $request; + $post = $this->createMock(ParameterBag::class); + $post->method('get') + ->willReturn($fieldId); + $post->method('all') + ->willReturn($map); + $request->request = $post; + + $request->expects($this->any()) + ->method('duplicate') + ->willReturn($request); + + $requestStack = $this->createMock(RequestStack::class); + $requestStack->expects($this->any()) + ->method('getCurrentRequest') + ->willReturn($request); + + return $requestStack; } } diff --git a/Tests/Unit/Controller/CustomField/FormControllerTest.php b/Tests/Unit/Controller/CustomField/FormControllerTest.php index 6c499705e..b6f5cb629 100644 --- a/Tests/Unit/Controller/CustomField/FormControllerTest.php +++ b/Tests/Unit/Controller/CustomField/FormControllerTest.php @@ -4,6 +4,7 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\CustomField; +use Mautic\CoreBundle\Security\Permissions\CorePermissions; use MauticPlugin\CustomObjectsBundle\Controller\CustomField\FormController; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomFieldFactory; @@ -16,57 +17,98 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldRouteProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectRouteProvider; +use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Form\FormFactory; use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; class FormControllerTest extends AbstractFieldControllerTest { + /** + * @var MockObject|RequestStack + */ + protected $requestStack; + + /** + * @var MockObject|CorePermissions + */ + protected $security; + + /** + * @var MockObject|FormFactory + */ private $formFactory; + + /** + * @var MockObject|CustomFieldModel + */ private $customFieldModel; + + /** + * @var MockObject|CustomFieldFactory + */ private $customFieldFactory; + + /** + * @var MockObject|CustomFieldPermissionProvider + */ private $permissionProvider; + + /** + * @var MockObject|CustomFieldRouteProvider + */ private $fieldRouteProvider; + + /** + * @var MockObject|CustomObjectModel + */ private $customObjectModel; + + /** + * @var MockObject|CustomObjectRouteProvider + */ private $objectRouteProvider; + + /** + * @var MockObject|FormInterface + */ private $form; + + /** + * @var MockObject|FormController + */ private $formController; protected function setUp(): void { parent::setUp(); - $this->formFactory = $this->createMock(FormFactory::class); - $this->customFieldModel = $this->createMock(CustomFieldModel::class); - $this->customFieldFactory = $this->createMock(CustomFieldFactory::class); - $this->permissionProvider = $this->createMock(CustomFieldPermissionProvider::class); - $this->fieldRouteProvider = $this->createMock(CustomFieldRouteProvider::class); - $this->customObjectModel = $this->createMock(CustomObjectModel::class); - $this->objectRouteProvider = $this->createMock(CustomObjectRouteProvider::class); - $this->form = $this->createMock(FormInterface::class); - - $this->formController = new FormController( - $this->formFactory, - $this->customFieldModel, - $this->customFieldFactory, - $this->permissionProvider, - $this->fieldRouteProvider, - $this->customObjectModel, - $this->objectRouteProvider - ); - - $this->addSymfonyDependencies($this->formController); + $this->formFactory = $this->createMock(FormFactory::class); + $this->customFieldModel = $this->createMock(CustomFieldModel::class); + $this->customFieldFactory = $this->createMock(CustomFieldFactory::class); + $this->permissionProvider = $this->createMock(CustomFieldPermissionProvider::class); + $this->fieldRouteProvider = $this->createMock(CustomFieldRouteProvider::class); + $this->customObjectModel = $this->createMock(CustomObjectModel::class); + $this->objectRouteProvider = $this->createMock(CustomObjectRouteProvider::class); + $this->form = $this->createMock(FormInterface::class); } - public function testRenderFormIfCustomFieldNotFound(): void + public function testRenderFormIfCustomFieldNotFoundFormController(): void { - $objectId = 1; - $fieldId = 2; - $fieldType = 'text'; - $panelId = null; - $panelCount = null; - - $request = $this->createRequestMock($objectId, $fieldId, $fieldType, $panelId, $panelCount); + $objectId = 1; + $fieldId = 2; + $fieldType = 'text'; + $panelId = null; + $panelCount = null; + + $this->createFormController( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount + ); $this->customFieldModel->expects($this->once()) ->method('fetchEntity') @@ -75,18 +117,42 @@ public function testRenderFormIfCustomFieldNotFound(): void $this->permissionProvider->expects($this->never()) ->method('canEdit'); - $this->formController->renderFormAction($request); + $this->translator->expects($this->once()) + ->method('trans') + ->with( + 'not found message', + [ + '%url%' => null, + ] + ) + ->willReturn('not found message'); + + $this->formController->renderFormAction( + $this->formFactory, + $this->customFieldModel, + $this->customFieldFactory, + $this->permissionProvider, + $this->fieldRouteProvider, + $this->customObjectModel, + $this->objectRouteProvider + ); } public function testRenderFormIfCustomFieldAccessDenied(): void { - $objectId = 1; - $fieldId = 2; - $fieldType = 'text'; - $panelId = null; - $panelCount = null; - - $request = $this->createRequestMock($objectId, $fieldId, $fieldType, $panelId, $panelCount); + $objectId = 1; + $fieldId = 2; + $fieldType = 'text'; + $panelId = null; + $panelCount = null; + + $this->createFormController( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount + ); $this->customFieldModel->expects($this->once()) ->method('fetchEntity') @@ -97,20 +163,38 @@ public function testRenderFormIfCustomFieldAccessDenied(): void ->method('canEdit') ->will($this->throwException(new ForbiddenException('forbidden message'))); + $this->security->expects($this->once()) + ->method('isAnonymous') + ->willReturn(true); + $this->expectException(AccessDeniedHttpException::class); - $this->formController->renderFormAction($request); + $this->formController->renderFormAction( + $this->formFactory, + $this->customFieldModel, + $this->customFieldFactory, + $this->permissionProvider, + $this->fieldRouteProvider, + $this->customObjectModel, + $this->objectRouteProvider + ); } public function testRenderFormActionEditField(): void { - $objectId = 1; - $fieldId = 2; - $fieldType = 'text'; - $panelId = null; - $panelCount = null; - - $request = $this->createRequestMock($objectId, $fieldId, $fieldType, $panelId, $panelCount); + $objectId = 1; + $fieldId = 2; + $fieldType = 'text'; + $panelId = null; + $panelCount = null; + + $this->createFormController( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount + ); $customObject = new CustomObject(); $this->customObjectModel->expects($this->once()) @@ -138,7 +222,13 @@ public function testRenderFormActionEditField(): void $action = 'action'; $this->fieldRouteProvider->expects($this->once()) ->method('buildSaveRoute') - ->with($fieldType, $fieldId, $customObject->getId(), $panelCount, $panelId) + ->with( + $fieldType, + $fieldId, + $customObject->getId(), + $panelCount, + $panelId + ) ->willReturn($action); $this->formFactory->expects($this->once()) @@ -157,7 +247,15 @@ public function testRenderFormActionEditField(): void ->method('createView') ->willReturn($view); - $this->formController->renderFormAction($request); + $this->formController->renderFormAction( + $this->formFactory, + $this->customFieldModel, + $this->customFieldFactory, + $this->permissionProvider, + $this->fieldRouteProvider, + $this->customObjectModel, + $this->objectRouteProvider + ); } public function testRenderFormActionCreateField(): void @@ -168,7 +266,13 @@ public function testRenderFormActionCreateField(): void $panelId = null; $panelCount = null; - $request = $this->createRequestMock($objectId, $fieldId, $fieldType, $panelId, $panelCount); + $this->createFormController( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount + ); $this->permissionProvider->expects($this->once()) ->method('canCreate'); @@ -209,6 +313,49 @@ public function testRenderFormActionCreateField(): void ->method('createView') ->willReturn($view); - $this->formController->renderFormAction($request); + $this->formController->renderFormAction( + $this->formFactory, + $this->customFieldModel, + $this->customFieldFactory, + $this->permissionProvider, + $this->fieldRouteProvider, + $this->customObjectModel, + $this->objectRouteProvider + ); + } + + private function createFormController( + ?int $objectId, + ?int $fieldId, + string $fieldType, + ?int $panelId = null, + ?int $panelCount = null + ): void { + $this->requestStack = $this->createRequestStackMock( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount + ); + + $this->formController = new FormController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, + $this->flashBag, + $this->requestStack, + $this->security + ); + + $this->addSymfonyDependencies($this->formController); + + $this->container->get('http_kernel')->expects($this->any()) + ->method('handle') + ->willreturn(null); } } diff --git a/Tests/Unit/Controller/CustomField/SaveControllerTest.php b/Tests/Unit/Controller/CustomField/SaveControllerTest.php index 6c3541738..c9fce0446 100644 --- a/Tests/Unit/Controller/CustomField/SaveControllerTest.php +++ b/Tests/Unit/Controller/CustomField/SaveControllerTest.php @@ -20,12 +20,10 @@ use Symfony\Component\Form\FormFactory; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; -use Symfony\Component\Translation\TranslatorInterface; class SaveControllerTest extends AbstractFieldControllerTest { private $formFactory; - private $translator; private $customFieldModel; private $customFieldFactory; private $permissionProvider; @@ -39,36 +37,29 @@ protected function setUp(): void parent::setUp(); $this->formFactory = $this->createMock(FormFactory::class); - $this->translator = $this->createMock(TranslatorInterface::class); $this->customFieldModel = $this->createMock(CustomFieldModel::class); $this->customFieldFactory = $this->createMock(CustomFieldFactory::class); $this->permissionProvider = $this->createMock(CustomFieldPermissionProvider::class); $this->fieldRouteProvider = $this->createMock(CustomFieldRouteProvider::class); $this->customObjectModel = $this->createMock(CustomObjectModel::class); $this->form = $this->createMock(FormInterface::class); - - $this->saveController = new SaveController( - $this->formFactory, - $this->translator, - $this->customFieldModel, - $this->customFieldFactory, - $this->permissionProvider, - $this->fieldRouteProvider, - $this->customObjectModel - ); - - $this->addSymfonyDependencies($this->saveController); } public function testRenderFormIfCustomFieldNotFound(): void { - $objectId = 1; - $fieldId = 2; - $fieldType = 'text'; - $panelId = null; - $panelCount = null; - - $request = $this->createRequestMock($objectId, $fieldId, $fieldType, $panelId, $panelCount); + $objectId = 1; + $fieldId = 2; + $fieldType = 'text'; + $panelId = null; + $panelCount = null; + + $this->createSaveController( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount + ); $this->customFieldModel->expects($this->once()) ->method('fetchEntity') @@ -77,7 +68,14 @@ public function testRenderFormIfCustomFieldNotFound(): void $this->permissionProvider->expects($this->never()) ->method('canEdit'); - $this->saveController->saveAction($request); + $this->saveController->saveAction( + $this->formFactory, + $this->customFieldModel, + $this->customFieldFactory, + $this->permissionProvider, + $this->fieldRouteProvider, + $this->customObjectModel + ); } public function testRenderFormIfCustomFieldAccessDenied(): void @@ -88,7 +86,13 @@ public function testRenderFormIfCustomFieldAccessDenied(): void $panelId = null; $panelCount = null; - $request = $this->createRequestMock($objectId, $fieldId, $fieldType, $panelId, $panelCount); + $this->createSaveController( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount + ); $this->customFieldModel->expects($this->once()) ->method('fetchEntity') @@ -101,7 +105,14 @@ public function testRenderFormIfCustomFieldAccessDenied(): void $this->expectException(AccessDeniedHttpException::class); - $this->saveController->saveAction($request); + $this->saveController->saveAction( + $this->formFactory, + $this->customFieldModel, + $this->customFieldFactory, + $this->permissionProvider, + $this->fieldRouteProvider, + $this->customObjectModel + ); } public function testSaveActionEdit(): void @@ -112,6 +123,14 @@ public function testSaveActionEdit(): void $panelId = null; $panelCount = null; + $this->createSaveController( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount + ); + $customObject = $this->createMock(CustomObject::class); $customObject->expects($this->once()) ->method('getId') @@ -124,7 +143,15 @@ public function testSaveActionEdit(): void ['custom_field', null, []], ['panelId', null, $panelCount], ]; - $request = $this->createRequestMock($objectId, $fieldId, $fieldType, $panelId, $panelCount, $mapExtras); + + $this->createSaveController( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount, + $mapExtras + ); $this->customObjectModel->expects($this->once()) ->method('fetchEntity') @@ -157,7 +184,7 @@ public function testSaveActionEdit(): void $this->form->expects($this->once()) ->method('handleRequest') - ->with($request); + ->with($this->requestStack->getCurrentRequest()); $this->form->expects($this->once()) ->method('isValid') @@ -181,7 +208,14 @@ public function testSaveActionEdit(): void $customObject->expects($this->once()) ->method('setCustomFields'); - $this->saveController->saveAction($request); + $this->saveController->saveAction( + $this->formFactory, + $this->customFieldModel, + $this->customFieldFactory, + $this->permissionProvider, + $this->fieldRouteProvider, + $this->customObjectModel + ); } public function testSaveActionCreate(): void @@ -192,6 +226,14 @@ public function testSaveActionCreate(): void $panelId = null; $panelCount = null; + $this->createSaveController( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount + ); + $customObject = $this->createMock(CustomObject::class); $customObject->expects($this->once()) ->method('getId') @@ -206,7 +248,15 @@ public function testSaveActionCreate(): void ['panelCount', null, $panelCount], ['custom_field', null, []], ]; - $request = $this->createRequestMock($objectId, $fieldId, $fieldType, $panelId, $panelCount, $mapExtras); + + $this->createSaveController( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount, + $mapExtras + ); $this->customObjectModel->expects($this->once()) ->method('fetchEntity') @@ -239,7 +289,7 @@ public function testSaveActionCreate(): void $this->form->expects($this->once()) ->method('handleRequest') - ->with($request); + ->with($this->requestStack->getCurrentRequest()); $this->form->expects($this->once()) ->method('isValid') @@ -260,7 +310,14 @@ public function testSaveActionCreate(): void $customObject->expects($this->once()) ->method('setCustomFields'); - $this->saveController->saveAction($request); + $this->saveController->saveAction( + $this->formFactory, + $this->customFieldModel, + $this->customFieldFactory, + $this->permissionProvider, + $this->fieldRouteProvider, + $this->customObjectModel + ); } public function testInvalidPost(): void @@ -282,7 +339,15 @@ public function testInvalidPost(): void ['custom_field', null, []], ['custom_field', null, []], ]; - $request = $this->createRequestMock($objectId, $fieldId, $fieldType, $panelId, $panelCount, $mapExtras); + + $this->createSaveController( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount, + $mapExtras + ); $this->customObjectModel->expects($this->once()) ->method('fetchEntity') @@ -311,12 +376,52 @@ public function testInvalidPost(): void $this->form->expects($this->once()) ->method('handleRequest') - ->with($request); + ->with($this->requestStack->getCurrentRequest()); $this->form->expects($this->once()) ->method('isValid') ->willReturn(false); - $this->saveController->saveAction($request); + $this->saveController->saveAction( + $this->formFactory, + $this->customFieldModel, + $this->customFieldFactory, + $this->permissionProvider, + $this->fieldRouteProvider, + $this->customObjectModel + ); + } + + private function createSaveController( + ?int $objectId, + ?int $fieldId, + string $fieldType, + ?int $panelId = null, + ?int $panelCount = null, + array $mapExtras = [] + ): void { + $this->requestStack = $this->createRequestStackMock( + $objectId, + $fieldId, + $fieldType, + $panelId, + $panelCount, + $mapExtras + ); + + $this->saveController = new SaveController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, + $this->flashBag, + $this->requestStack, + $this->security + ); + + $this->addSymfonyDependencies($this->saveController); } } diff --git a/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php b/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php index 695c88f20..dc4d8cd7d 100644 --- a/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php +++ b/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php @@ -4,6 +4,7 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\CustomItem; +use Mautic\CoreBundle\Model\NotificationModel; use Mautic\CoreBundle\Service\FlashBag; use MauticPlugin\CustomObjectsBundle\Controller\CustomItem\BatchDeleteController; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; @@ -16,15 +17,16 @@ use MauticPlugin\CustomObjectsBundle\Provider\SessionProviderFactory; use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; +#[\AllowDynamicProperties] class BatchDeleteControllerTest extends ControllerTestCase { private $customItemModel; private $sessionProvider; - private $flashBag; + private $sessionProviderFactory; private $permissionProvider; private $routeProvider; + private $model; /** * @var BatchDeleteController @@ -35,27 +37,43 @@ protected function setUp(): void { parent::setUp(); - $sessionProviderFactory = $this->createMock(SessionProviderFactory::class); - $this->requestStack = $this->createMock(RequestStack::class); - $this->customItemModel = $this->createMock(CustomItemModel::class); - $this->sessionProvider = $this->createMock(SessionProvider::class); - $this->flashBag = $this->createMock(FlashBag::class); - $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); - $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); - $this->request = $this->createMock(Request::class); - $this->batchDeleteController = new BatchDeleteController( + $this->customItemModel = $this->createMock(CustomItemModel::class); + $this->sessionProvider = $this->createMock(SessionProvider::class); + $this->sessionProviderFactory = $this->createMock(SessionProviderFactory::class); + $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); + $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); + $this->request = $this->createMock(Request::class); + + $this->requestStack->expects($this->any()) + ->method('getCurrentRequest') + ->willReturn($this->request); + + $this->model = $this->createMock(NotificationModel::class); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->batchDeleteController = new BatchDeleteController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, + $this->flashBag, $this->requestStack, - $this->customItemModel, - $sessionProviderFactory, - $this->permissionProvider, - $this->routeProvider, - $this->flashBag + $this->security ); $this->addSymfonyDependencies($this->batchDeleteController); $this->request->method('isXmlHttpRequest')->willReturn(true); - $sessionProviderFactory->method('createItemProvider')->willReturn($this->sessionProvider); + $this->sessionProviderFactory->method('createItemProvider')->willReturn($this->sessionProvider); + + $this->model->expects($this->once()) + ->method('getNotificationContent') + ->willReturn([[], 'test', 'test']); } public function testDeleteActionIfCustomItemNotFound(): void @@ -79,7 +97,14 @@ public function testDeleteActionIfCustomItemNotFound(): void ->method('add') ->with('custom.item.error.items.not.found', ['%ids%' => '13,14'], FlashBag::LEVEL_ERROR); - $this->batchDeleteController->deleteAction(33); + $this->batchDeleteController->deleteAction( + $this->customItemModel, + $this->sessionProviderFactory, + $this->permissionProvider, + $this->routeProvider, + $this->flashBag, + 33 + ); } public function testDeleteActionIfCustomItemForbidden(): void @@ -107,7 +132,14 @@ public function testDeleteActionIfCustomItemForbidden(): void ->method('add') ->with('custom.item.error.items.denied', ['%ids%' => '13,14'], FlashBag::LEVEL_ERROR); - $this->batchDeleteController->deleteAction(33); + $this->batchDeleteController->deleteAction( + $this->customItemModel, + $this->sessionProviderFactory, + $this->permissionProvider, + $this->routeProvider, + $this->flashBag, + 33 + ); } public function testDeleteAction(): void @@ -144,6 +176,13 @@ public function testDeleteAction(): void ->method('buildListRoute') ->with(33, 3); - $this->batchDeleteController->deleteAction(33); + $this->batchDeleteController->deleteAction( + $this->customItemModel, + $this->sessionProviderFactory, + $this->permissionProvider, + $this->routeProvider, + $this->flashBag, + 33 + ); } } diff --git a/Tests/Unit/Controller/CustomItem/CancelControllerTest.php b/Tests/Unit/Controller/CustomItem/CancelControllerTest.php index 22f0fd3d0..788cedfc5 100644 --- a/Tests/Unit/Controller/CustomItem/CancelControllerTest.php +++ b/Tests/Unit/Controller/CustomItem/CancelControllerTest.php @@ -12,11 +12,13 @@ use MauticPlugin\CustomObjectsBundle\Provider\SessionProvider; use MauticPlugin\CustomObjectsBundle\Provider\SessionProviderFactory; use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; +use Symfony\Component\HttpFoundation\Request; class CancelControllerTest extends ControllerTestCase { private const OBJECT_ID = 33; + private $sessionProviderFactory; private $sessionProvider; private $routeProvider; private $customItemModel; @@ -30,20 +32,32 @@ protected function setUp(): void { parent::setUp(); - $sessionProviderFactory = $this->createMock(SessionProviderFactory::class); - $this->sessionProvider = $this->createMock(SessionProvider::class); - $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); - $this->customItemModel = $this->createMock(CustomItemModel::class); - - $this->cancelController = new CancelController( - $sessionProviderFactory, - $this->routeProvider, - $this->customItemModel + $this->sessionProviderFactory = $this->createMock(SessionProviderFactory::class); + $this->sessionProvider = $this->createMock(SessionProvider::class); + $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); + $this->customItemModel = $this->createMock(CustomItemModel::class); + $this->request = $this->createMock(Request::class); + + $this->requestStack->expects($this->any()) + ->method('getCurrentRequest') + ->willReturn($this->request); + + $this->cancelController = new CancelController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, + $this->flashBag, + $this->requestStack, + $this->security ); $this->addSymfonyDependencies($this->cancelController); - $sessionProviderFactory->method('createItemProvider')->willReturn($this->sessionProvider); + $this->sessionProviderFactory->method('createItemProvider')->willReturn($this->sessionProvider); } public function testCancelAction(): void @@ -62,7 +76,12 @@ public function testCancelAction(): void ->with(self::OBJECT_ID, $pageNumber) ->willReturn('some/route'); - $this->cancelController->cancelAction(self::OBJECT_ID); + $this->cancelController->cancelAction( + $this->sessionProviderFactory, + $this->routeProvider, + $this->customItemModel, + self::OBJECT_ID + ); } public function testCancelActionWithEntityUnlock(): void @@ -89,6 +108,12 @@ public function testCancelActionWithEntityUnlock(): void ->with(self::OBJECT_ID, $pageNumber) ->willReturn('some/route'); - $this->cancelController->cancelAction(self::OBJECT_ID, $customItemId); + $this->cancelController->cancelAction( + $this->sessionProviderFactory, + $this->routeProvider, + $this->customItemModel, + self::OBJECT_ID, + $customItemId + ); } } diff --git a/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php b/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php index 36b2a7e82..fcb3e8393 100644 --- a/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php +++ b/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php @@ -4,7 +4,7 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\CustomItem; -use Mautic\CoreBundle\Service\FlashBag; +use Mautic\CoreBundle\Model\NotificationModel; use MauticPlugin\CustomObjectsBundle\Controller\CustomItem\DeleteController; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Exception\ForbiddenException; @@ -15,9 +15,11 @@ use MauticPlugin\CustomObjectsBundle\Provider\SessionProvider; use MauticPlugin\CustomObjectsBundle\Provider\SessionProviderFactory; use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; +use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +#[\AllowDynamicProperties] class DeleteControllerTest extends ControllerTestCase { private const OBJECT_ID = 33; @@ -26,7 +28,6 @@ class DeleteControllerTest extends ControllerTestCase private $customItemModel; private $sessionProvider; - private $flashBag; private $permissionProvider; private $routeProvider; @@ -39,26 +40,37 @@ protected function setUp(): void { parent::setUp(); - $sessionProviderFactory = $this->createMock(SessionProviderFactory::class); - $this->customItemModel = $this->createMock(CustomItemModel::class); - $this->sessionProvider = $this->createMock(SessionProvider::class); - $this->flashBag = $this->createMock(FlashBag::class); - $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); - $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); - $this->request = $this->createMock(Request::class); - $this->deleteController = new DeleteController( - $this->customItemModel, - $sessionProviderFactory, + $this->sessionProviderFactory = $this->createMock(SessionProviderFactory::class); + $this->customItemModel = $this->createMock(CustomItemModel::class); + $this->sessionProvider = $this->createMock(SessionProvider::class); + $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); + $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); + $this->request = $this->createMock(Request::class); + + $this->requestStack->expects($this->any()) + ->method('getCurrentRequest') + ->willReturn($this->request); + + $this->model = $this->createMock(NotificationModel::class); + + $this->deleteController = new DeleteController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, $this->flashBag, - $this->permissionProvider, - $this->routeProvider + $this->requestStack, + $this->security ); $this->addSymfonyDependencies($this->deleteController); $this->request->method('isXmlHttpRequest')->willReturn(true); $this->request->method('getRequestUri')->willReturn('https://a.b'); - $sessionProviderFactory->method('createItemProvider')->willReturn($this->sessionProvider); + $this->sessionProviderFactory->method('createItemProvider')->willReturn($this->sessionProvider); } public function testDeleteActionIfCustomItemNotFound(): void @@ -73,7 +85,25 @@ public function testDeleteActionIfCustomItemNotFound(): void $this->flashBag->expects($this->never()) ->method('add'); - $this->deleteController->deleteAction(self::OBJECT_ID, self::ITEM_ID); + $this->translator->expects($this->once()) + ->method('trans') + ->willReturn('Item not found message'); + + $post = $this->createMock(ParameterBag::class); + $this->request->request = $post; + $post->expects($this->once()) + ->method('all') + ->willReturn([]); + + $this->deleteController->deleteAction( + $this->customItemModel, + $this->sessionProviderFactory, + $this->flashBag, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testDeleteActionIfCustomItemForbidden(): void @@ -92,9 +122,21 @@ public function testDeleteActionIfCustomItemForbidden(): void $this->flashBag->expects($this->never()) ->method('add'); + $this->security->expects($this->once()) + ->method('isAnonymous') + ->willReturn(true); + $this->expectException(AccessDeniedHttpException::class); - $this->deleteController->deleteAction(self::OBJECT_ID, self::ITEM_ID); + $this->deleteController->deleteAction( + $this->customItemModel, + $this->sessionProviderFactory, + $this->flashBag, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testDeleteAction(): void @@ -124,6 +166,18 @@ public function testDeleteAction(): void ->method('buildListRoute') ->with(self::OBJECT_ID, 3); - $this->deleteController->deleteAction(self::OBJECT_ID, self::ITEM_ID); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->deleteController->deleteAction( + $this->customItemModel, + $this->sessionProviderFactory, + $this->flashBag, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } } diff --git a/Tests/Unit/Controller/CustomItem/FormControllerTest.php b/Tests/Unit/Controller/CustomItem/FormControllerTest.php index 54fd0cb5a..cb98a6de2 100644 --- a/Tests/Unit/Controller/CustomItem/FormControllerTest.php +++ b/Tests/Unit/Controller/CustomItem/FormControllerTest.php @@ -4,6 +4,7 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\CustomItem; +use Mautic\CoreBundle\Model\NotificationModel; use Mautic\UserBundle\Entity\User; use MauticPlugin\CustomObjectsBundle\Controller\CustomItem\FormController; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; @@ -21,9 +22,11 @@ use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Form\FormFactory; use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +#[\AllowDynamicProperties] class FormControllerTest extends ControllerTestCase { public const OBJECT_ID = 33; @@ -86,23 +89,36 @@ protected function setUp(): void { parent::setUp(); - $this->customItemModel = $this->createMock(CustomItemModel::class); - $this->customObjectModel = $this->createMock(CustomObjectModel::class); - $this->formFactory = $this->createMock(FormFactory::class); - $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); - $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); - $this->lockFlashMessageHelper = $this->createMock(LockFlashMessageHelper::class); - $this->request = $this->createMock(Request::class); - $this->customObject = $this->createMock(CustomObject::class); - $this->customItem = $this->createMock(CustomItem::class); - $this->form = $this->createMock(FormInterface::class); - $this->formController = new FormController( - $this->formFactory, - $this->customObjectModel, - $this->customItemModel, - $this->permissionProvider, - $this->routeProvider, - $this->lockFlashMessageHelper + $this->customItemModel = $this->createMock(CustomItemModel::class); + $this->customObjectModel = $this->createMock(CustomObjectModel::class); + $this->formFactory = $this->createMock(FormFactory::class); + $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); + $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); + $this->lockFlashMessageHelper = $this->createMock(LockFlashMessageHelper::class); + $this->request = $this->createMock(Request::class); + $this->customObject = $this->createMock(CustomObject::class); + $this->customItem = $this->createMock(CustomItem::class); + $this->form = $this->createMock(FormInterface::class); + $this->model = $this->createMock(NotificationModel::class); + + $userMock = $this->createMock(User::class); + $userMock->method('isAdmin') + ->willReturn(true); + + $this->userHelper->expects($this->any())->method('getUser') + ->willReturn($userMock); + + $this->formController = new FormController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, + $this->flashBag, + $this->requestStack, + $this->security ); $this->addSymfonyDependencies($this->formController); @@ -133,9 +149,20 @@ public function testNewActionIfForbidden(): void $this->routeProvider->expects($this->never()) ->method('buildNewRoute'); + $this->security->expects($this->once()) + ->method('isAnonymous') + ->willReturn(true); + $this->expectException(AccessDeniedHttpException::class); - $this->formController->newAction(self::OBJECT_ID); + $this->formController->newAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + self::OBJECT_ID + ); } public function testNewWithRedirectToContactActionIfForbidden(): void @@ -155,7 +182,15 @@ public function testNewWithRedirectToContactActionIfForbidden(): void $this->expectException(AccessDeniedHttpException::class); - $this->formController->newWithRedirectToContactAction(static::OBJECT_ID, static::CONTACT_ID); + $this->formController->newWithRedirectToContactAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + static::OBJECT_ID, + static::CONTACT_ID + ); } public function testNewAction(): void @@ -178,7 +213,22 @@ public function testNewAction(): void $this->assertRenderFormForItem($this->customItem); - $this->formController->newAction(self::OBJECT_ID); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->formController->newAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + self::OBJECT_ID + ); } public function testNewWithRedirectToContactAction(): void @@ -191,7 +241,7 @@ public function getId() }; $customItem = new class($customObject) extends CustomItem { - public function getId() + public function getId(): int { return FormControllerTest::ITEM_ID; } @@ -215,7 +265,19 @@ public function getId() $this->assertRenderFormForItem($customItem, static::CONTACT_ID); - $this->formController->newWithRedirectToContactAction(static::OBJECT_ID, static::CONTACT_ID); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->formController->newWithRedirectToContactAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + static::OBJECT_ID, + static::CONTACT_ID + ); } public function testNewWithRedirectToContactActionWithChildObject(): void @@ -282,7 +344,19 @@ function ($newCustomItem) { ) ->willReturn($this->form); - $this->formController->newWithRedirectToContactAction(static::OBJECT_ID, static::CONTACT_ID); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->formController->newWithRedirectToContactAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + static::OBJECT_ID, + static::CONTACT_ID + ); } public function testEditActionIfCustomItemNotFound(): void @@ -294,7 +368,21 @@ public function testEditActionIfCustomItemNotFound(): void $this->routeProvider->expects($this->never()) ->method('buildEditRoute'); - $this->formController->editAction(self::OBJECT_ID, self::ITEM_ID); + $post = $this->createMock(ParameterBag::class); + $this->request->request = $post; + $post->expects($this->once()) + ->method('all') + ->willReturn([]); + + $this->formController->editAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->lockFlashMessageHelper, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testEditActionIfCustomItemForbidden(): void @@ -312,7 +400,15 @@ public function testEditActionIfCustomItemForbidden(): void $this->expectException(AccessDeniedHttpException::class); - $this->formController->editAction(self::OBJECT_ID, self::ITEM_ID); + $this->formController->editAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->lockFlashMessageHelper, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testEditAction(): void @@ -338,7 +434,19 @@ public function testEditAction(): void $this->assertRenderFormForItem($this->customItem); - $this->formController->editAction(self::OBJECT_ID, self::ITEM_ID); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->formController->editAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->lockFlashMessageHelper, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testEditWithRedirectToContactAction(): void @@ -351,7 +459,7 @@ public function getId() }; $customItem = new class($customObject) extends CustomItem { - public function getId() + public function getId(): int { return FormControllerTest::ITEM_ID; } @@ -378,7 +486,20 @@ public function getId() $this->assertRenderFormForItem($customItem, static::CONTACT_ID); - $this->formController->editWithRedirectToContactAction(self::OBJECT_ID, self::ITEM_ID, static::CONTACT_ID); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->formController->editWithRedirectToContactAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->lockFlashMessageHelper, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID, + static::CONTACT_ID + ); } public function testEditWithRedirectToContactActionWithChildObject(): void @@ -401,7 +522,7 @@ public function getId() }; $customItem = new class($customObject) extends CustomItem { - public function getId() + public function getId(): int { return FormControllerTest::ITEM_ID; } @@ -409,7 +530,7 @@ public function getId() public function findChildCustomItem(): CustomItem { return new class($this->getCustomObject()->getRelationshipObject()) extends CustomItem { - public function getId() + public function getId(): int { return 777; } @@ -452,7 +573,20 @@ function (CustomItem $childCustomItem) { $this->assertRenderFormForItem($customItem, static::CONTACT_ID); - $this->formController->editWithRedirectToContactAction(self::OBJECT_ID, self::ITEM_ID, static::CONTACT_ID); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->formController->editWithRedirectToContactAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->lockFlashMessageHelper, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID, + static::CONTACT_ID + ); } public function testEditWithRedirectToContactActionIfCustomItemNotFound(): void @@ -464,7 +598,22 @@ public function testEditWithRedirectToContactActionIfCustomItemNotFound(): void $this->routeProvider->expects($this->never()) ->method('buildEditRouteWithRedirectToContact'); - $this->formController->editWithRedirectToContactAction(self::OBJECT_ID, self::ITEM_ID, static::CONTACT_ID); + $post = $this->createMock(ParameterBag::class); + $this->request->request = $post; + $post->expects($this->once()) + ->method('all') + ->willReturn([]); + + $this->formController->editWithRedirectToContactAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->lockFlashMessageHelper, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID, + static::CONTACT_ID + ); } public function testEditWithRedirectToContactActionIfCustomItemForbidden(): void @@ -482,7 +631,16 @@ public function testEditWithRedirectToContactActionIfCustomItemForbidden(): void $this->expectException(AccessDeniedHttpException::class); - $this->formController->editWithRedirectToContactAction(self::OBJECT_ID, self::ITEM_ID, static::CONTACT_ID); + $this->formController->editWithRedirectToContactAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->lockFlashMessageHelper, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID, + static::CONTACT_ID + ); } public function testEditWithRedirectToContactActionWhenTheItemIsLocked() @@ -500,21 +658,21 @@ public function testEditWithRedirectToContactActionWhenTheItemIsLocked() ->method('buildEditRouteWithRedirectToContact') ->with(self::OBJECT_ID, self::ITEM_ID, static::CONTACT_ID); - $userMock = $this->createMock(User::class); - $this->userHelper->expects($this->once()) - ->method('getUser') - ->willReturn($userMock); - - $userMock->expects($this->once()) - ->method('isAdmin') - ->willReturn(true); - $this->routeProvider->expects($this->once()) ->method('buildViewRoute') ->with(static::OBJECT_ID, static::ITEM_ID) ->willReturn('https://redirect.url'); - $this->formController->editWithRedirectToContactAction(self::OBJECT_ID, self::ITEM_ID, static::CONTACT_ID); + $this->formController->editWithRedirectToContactAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->lockFlashMessageHelper, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID, + static::CONTACT_ID + ); } public function testEditActionWhenTheItemIsLocked() @@ -532,21 +690,20 @@ public function testEditActionWhenTheItemIsLocked() ->method('buildEditRoute') ->with(self::OBJECT_ID, self::ITEM_ID); - $userMock = $this->createMock(User::class); - $this->userHelper->expects($this->once()) - ->method('getUser') - ->willReturn($userMock); - - $userMock->expects($this->once()) - ->method('isAdmin') - ->willReturn(true); - $this->routeProvider->expects($this->once()) ->method('buildViewRoute') ->with(static::OBJECT_ID, static::ITEM_ID) ->willReturn('https://redirect.url'); - $this->formController->editAction(self::OBJECT_ID, self::ITEM_ID); + $this->formController->editAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->lockFlashMessageHelper, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testCloneAction(): void @@ -567,7 +724,18 @@ public function testCloneAction(): void $this->assertRenderFormForItem($this->customItem); - $this->formController->cloneAction(self::OBJECT_ID, self::ITEM_ID); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->formController->cloneAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testCloneActionIfCustomItemNotFound(): void @@ -579,7 +747,20 @@ public function testCloneActionIfCustomItemNotFound(): void $this->routeProvider->expects($this->never()) ->method('buildCloneRoute'); - $this->formController->cloneAction(self::OBJECT_ID, self::ITEM_ID); + $post = $this->createMock(ParameterBag::class); + $this->request->request = $post; + $post->expects($this->once()) + ->method('all') + ->willReturn([]); + + $this->formController->cloneAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testCloneActionIfCustomItemForbidden(): void @@ -597,7 +778,14 @@ public function testCloneActionIfCustomItemForbidden(): void $this->expectException(AccessDeniedHttpException::class); - $this->formController->cloneAction(self::OBJECT_ID, self::ITEM_ID); + $this->formController->cloneAction( + $this->formFactory, + $this->routeProvider, + $this->customItemModel, + $this->permissionProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } private function assertRenderFormForItem(CustomItem $customItem, ?int $contactId = null): void diff --git a/Tests/Unit/Controller/CustomItem/LinkControllerTest.php b/Tests/Unit/Controller/CustomItem/LinkControllerTest.php index 88b5325ca..f401033ba 100644 --- a/Tests/Unit/Controller/CustomItem/LinkControllerTest.php +++ b/Tests/Unit/Controller/CustomItem/LinkControllerTest.php @@ -4,7 +4,7 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\CustomItem; -use Doctrine\DBAL\Driver\DriverException; +use Doctrine\DBAL\Driver\Exception as TheDriverException; use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Mautic\CoreBundle\Service\FlashBag; use MauticPlugin\CustomObjectsBundle\Controller\CustomItem\LinkController; @@ -14,7 +14,6 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; -use UnexpectedValueException; class LinkControllerTest extends ControllerTestCase { @@ -25,7 +24,7 @@ class LinkControllerTest extends ControllerTestCase private const ENTITY_TYPE = 'contact'; private $customItemModel; - private $flashBag; + private $permissionProvider; /** @@ -37,15 +36,9 @@ protected function setUp(): void { parent::setUp(); - $this->customItemModel = $this->createMock(CustomItemModel::class); - $this->flashBag = $this->createMock(FlashBag::class); - $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); - $this->linkController = new LinkController( - $this->customItemModel, - $this->permissionProvider, - $this->flashBag - ); - + $this->customItemModel = $this->createMock(CustomItemModel::class); + $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); + $this->linkController = new LinkController(); $this->addSymfonyDependencies($this->linkController); } @@ -62,7 +55,14 @@ public function testSaveActionIfCustomItemNotFound(): void ->method('add') ->with('Item not found message', [], FlashBag::LEVEL_ERROR); - $this->linkController->saveAction(self::ITEM_ID, self::ENTITY_TYPE, self::ENTITY_ID); + $this->linkController->saveAction( + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::ITEM_ID, + self::ENTITY_TYPE, + self::ENTITY_ID + ); } public function testSaveActionIfCustomItemIsLinkedAlready(): void @@ -72,8 +72,8 @@ public function testSaveActionIfCustomItemIsLinkedAlready(): void ->will( $this->throwException( new UniqueConstraintViolationException( - 'a message', - $this->createMock(DriverException::class) + $this->createMock(TheDriverException::class), + null ) ) ); @@ -89,7 +89,14 @@ public function testSaveActionIfCustomItemIsLinkedAlready(): void FlashBag::LEVEL_ERROR ); - $this->linkController->saveAction(self::ITEM_ID, self::ENTITY_TYPE, self::ENTITY_ID); + $this->linkController->saveAction( + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::ITEM_ID, + self::ENTITY_TYPE, + self::ENTITY_ID + ); } public function testSaveActionIfCustomItemForbidden(): void @@ -106,7 +113,14 @@ public function testSaveActionIfCustomItemForbidden(): void ->method('add') ->with('You do not have permission to edit', [], FlashBag::LEVEL_ERROR); - $this->linkController->saveAction(self::ITEM_ID, self::ENTITY_TYPE, self::ENTITY_ID); + $this->linkController->saveAction( + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::ITEM_ID, + self::ENTITY_TYPE, + self::ENTITY_ID + ); } public function testSaveActionIfCustomItemLinkedToUnknownEntityType(): void @@ -123,13 +137,20 @@ public function testSaveActionIfCustomItemLinkedToUnknownEntityType(): void $this->customItemModel->expects($this->once()) ->method('linkEntity') ->with($customItem, 'unicorn', self::ENTITY_ID) - ->will($this->throwException(new UnexpectedValueException('Entity unicorn cannot be linked to a custom item'))); + ->will($this->throwException(new \UnexpectedValueException('Entity unicorn cannot be linked to a custom item'))); $this->flashBag->expects($this->once()) ->method('add') ->with('Entity unicorn cannot be linked to a custom item', [], FlashBag::LEVEL_ERROR); - $this->linkController->saveAction(self::ITEM_ID, 'unicorn', self::ENTITY_ID); + $this->linkController->saveAction( + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::ITEM_ID, + 'unicorn', + self::ENTITY_ID + ); } public function testSaveAction(): void @@ -147,6 +168,13 @@ public function testSaveAction(): void ->method('linkEntity') ->with($customItem, self::ENTITY_TYPE, self::ENTITY_ID); - $this->linkController->saveAction(self::ITEM_ID, self::ENTITY_TYPE, self::ENTITY_ID); + $this->linkController->saveAction( + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::ITEM_ID, + self::ENTITY_TYPE, + self::ENTITY_ID + ); } } diff --git a/Tests/Unit/Controller/CustomItem/ListControllerTest.php b/Tests/Unit/Controller/CustomItem/ListControllerTest.php index 0484064e2..af5002b1d 100644 --- a/Tests/Unit/Controller/CustomItem/ListControllerTest.php +++ b/Tests/Unit/Controller/CustomItem/ListControllerTest.php @@ -18,9 +18,9 @@ use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +#[\AllowDynamicProperties] class ListControllerTest extends ControllerTestCase { private const OBJECT_ID = 33; @@ -32,6 +32,7 @@ class ListControllerTest extends ControllerTestCase private $sessionProvider; private $permissionProvider; private $routeProvider; + private $sessionProviderFactory; /** * @var ListController @@ -42,27 +43,31 @@ protected function setUp(): void { parent::setUp(); - $sessionProviderFactory = $this->createMock(SessionProviderFactory::class); - $this->requestStack = $this->createMock(RequestStack::class); - $this->customItemModel = $this->createMock(CustomItemModel::class); - $this->customObjectModel = $this->createMock(CustomObjectModel::class); - $this->sessionProvider = $this->createMock(SessionProvider::class); - $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); - $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); - $this->request = $this->createMock(Request::class); - $this->listController = new ListController( + $this->sessionProviderFactory = $this->createMock(SessionProviderFactory::class); + $this->customItemModel = $this->createMock(CustomItemModel::class); + $this->customObjectModel = $this->createMock(CustomObjectModel::class); + $this->sessionProvider = $this->createMock(SessionProvider::class); + $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); + $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); + $this->request = $this->createMock(Request::class); + + $this->listController = new ListController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, + $this->flashBag, $this->requestStack, - $sessionProviderFactory, - $this->customItemModel, - $this->customObjectModel, - $this->permissionProvider, - $this->routeProvider + $this->security ); $this->addSymfonyDependencies($this->listController); $this->requestStack->method('getCurrentRequest')->willReturn($this->request); - $sessionProviderFactory->method('createItemProvider')->willReturn($this->sessionProvider); + $this->sessionProviderFactory->method('createItemProvider')->willReturn($this->sessionProvider); } public function testListActionIfCustomObjectNotFound(): void @@ -74,7 +79,21 @@ public function testListActionIfCustomObjectNotFound(): void $this->customItemModel->expects($this->never()) ->method('getTableData'); - $this->listController->listAction(self::OBJECT_ID, self::PAGE); + $post = $this->createMock(ParameterBag::class); + $this->request->request = $post; + $post->expects($this->once()) + ->method('all') + ->willReturn([]); + + $this->listController->listAction( + $this->sessionProviderFactory, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID, + self::PAGE + ); } public function testListActionIfForbidden(): void @@ -86,9 +105,21 @@ public function testListActionIfForbidden(): void $this->customObjectModel->expects($this->never()) ->method('fetchEntity'); + $this->security->expects($this->once()) + ->method('isAnonymous') + ->willReturn(true); + $this->expectException(AccessDeniedHttpException::class); - $this->listController->listAction(self::OBJECT_ID, self::PAGE); + $this->listController->listAction( + $this->sessionProviderFactory, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID, + self::PAGE + ); } public function testListAction(): void @@ -148,7 +179,15 @@ public function testListAction(): void ->method('setPageLimit') ->with($pageLimit); - $this->listController->listAction(self::OBJECT_ID, self::PAGE); + $this->listController->listAction( + $this->sessionProviderFactory, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID, + self::PAGE + ); } public function testListActionWithQueryParamAndAjax(): void @@ -225,6 +264,14 @@ public function testListActionWithQueryParamAndAjax(): void ->method('setPageLimit') ->with($pageLimit); - $this->listController->listAction(self::OBJECT_ID, self::PAGE); + $this->listController->listAction( + $this->sessionProviderFactory, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID, + self::PAGE + ); } } diff --git a/Tests/Unit/Controller/CustomItem/LookupControllerTest.php b/Tests/Unit/Controller/CustomItem/LookupControllerTest.php index 5b3de0385..1363d77b3 100644 --- a/Tests/Unit/Controller/CustomItem/LookupControllerTest.php +++ b/Tests/Unit/Controller/CustomItem/LookupControllerTest.php @@ -12,15 +12,14 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; class LookupControllerTest extends ControllerTestCase { private const OBJECT_ID = 22; private $customItemModel; + private $permissionProvider; - private $flashBag; /** * @var LookupController @@ -32,16 +31,9 @@ protected function setUp(): void parent::setUp(); $this->customItemModel = $this->createMock(CustomItemModel::class); - $this->requestStack = $this->createMock(RequestStack::class); $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); - $this->flashBag = $this->createMock(FlashBag::class); $this->request = $this->createMock(Request::class); - $this->lookupController = new LookupController( - $this->requestStack, - $this->customItemModel, - $this->permissionProvider, - $this->flashBag - ); + $this->lookupController = new LookupController(); $this->addSymfonyDependencies($this->lookupController); } @@ -59,7 +51,13 @@ public function testListActionIfForbidden(): void $this->customItemModel->expects($this->never()) ->method('getLookupData'); - $this->lookupController->listAction(self::OBJECT_ID); + $this->lookupController->listAction( + $this->request, + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::OBJECT_ID + ); } public function testListAction(): void @@ -85,7 +83,13 @@ public function testListAction(): void return true; })); - $this->lookupController->listAction(self::OBJECT_ID); + $this->lookupController->listAction( + $this->request, + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::OBJECT_ID + ); } public function testListActionForContactEntity(): void @@ -116,6 +120,12 @@ public function testListActionForContactEntity(): void return true; })); - $this->lookupController->listAction(self::OBJECT_ID); + $this->lookupController->listAction( + $this->request, + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::OBJECT_ID + ); } } diff --git a/Tests/Unit/Controller/CustomItem/SaveControllerTest.php b/Tests/Unit/Controller/CustomItem/SaveControllerTest.php index 5f96f67cb..72927327c 100644 --- a/Tests/Unit/Controller/CustomItem/SaveControllerTest.php +++ b/Tests/Unit/Controller/CustomItem/SaveControllerTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\CustomItem; -use Mautic\CoreBundle\Service\FlashBag; use Mautic\UserBundle\Entity\User; use MauticPlugin\CustomObjectsBundle\Controller\CustomItem\SaveController; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; @@ -24,9 +23,9 @@ use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +#[\AllowDynamicProperties] class SaveControllerTest extends ControllerTestCase { public const OBJECT_ID = 33; @@ -50,11 +49,6 @@ class SaveControllerTest extends ControllerTestCase */ private $customObjectModel; - /** - * @var MockObject|FlashBag - */ - private $flashBag; - /** * @var MockObject|CustomItemPermissionProvider */ @@ -89,26 +83,34 @@ protected function setUp(): void { parent::setUp(); - $this->formFactory = $this->createMock(FormFactoryInterface::class); - $this->customItemModel = $this->createMock(CustomItemModel::class); - $this->customObjectModel = $this->createMock(CustomObjectModel::class); - $this->flashBag = $this->createMock(FlashBag::class); - $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); - $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); - $this->lockFlashMessageHelper = $this->createMock(LockFlashMessageHelper::class); - $this->requestStack = $this->createMock(RequestStack::class); - $this->request = new Request(); - $this->customItem = $this->createMock(CustomItem::class); - $this->form = $this->createMock(FormInterface::class); - $this->saveController = new SaveController( - $this->requestStack, - $this->formFactory, + $this->formFactory = $this->createMock(FormFactoryInterface::class); + $this->customItemModel = $this->createMock(CustomItemModel::class); + $this->customObjectModel = $this->createMock(CustomObjectModel::class); + $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); + $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); + $this->lockFlashMessageHelper = $this->createMock(LockFlashMessageHelper::class); + $this->request = new Request(); + $this->customItem = $this->createMock(CustomItem::class); + $this->form = $this->createMock(FormInterface::class); + + $userMock = $this->createMock(User::class); + $userMock->method('isAdmin') + ->willReturn(true); + + $this->userHelper->expects($this->any())->method('getUser') + ->willReturn($userMock); + + $this->saveController = new SaveController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, $this->flashBag, - $this->customItemModel, - $this->customObjectModel, - $this->permissionProvider, - $this->routeProvider, - $this->lockFlashMessageHelper + $this->requestStack, + $this->security ); $this->addSymfonyDependencies($this->saveController); @@ -132,7 +134,17 @@ public function testSaveActionIfExistingCustomItemNotFound(): void $this->permissionProvider->expects($this->never()) ->method('canCreate'); - $this->saveController->saveAction(self::OBJECT_ID, self::ITEM_ID); + $this->saveController->saveAction( + $this->formFactory, + $this->flashBag, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + $this->lockFlashMessageHelper, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testSaveActionIfExistingCustomItemIsForbidden(): void @@ -150,7 +162,17 @@ public function testSaveActionIfExistingCustomItemIsForbidden(): void $this->expectException(AccessDeniedHttpException::class); - $this->saveController->saveAction(self::OBJECT_ID, self::ITEM_ID); + $this->saveController->saveAction( + $this->formFactory, + $this->flashBag, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + $this->lockFlashMessageHelper, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testSaveActionForExistingCustomItemWithValidForm(): void @@ -248,7 +270,17 @@ public function testSaveActionForExistingCustomItemWithValidForm(): void Assert::assertSame(Request::METHOD_GET, $this->request->getMethod()); - $this->saveController->saveAction(self::OBJECT_ID, self::ITEM_ID); + $this->saveController->saveAction( + $this->formFactory, + $this->flashBag, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + $this->lockFlashMessageHelper, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testThatSaveActionRedirectToContactViewPageWhenContactIdIsSet(): void @@ -330,7 +362,17 @@ public function testThatSaveActionRedirectToContactViewPageWhenContactIdIsSet(): ->method('generate') ->willReturn('someRedirectUrl'); - $this->saveController->saveAction(self::OBJECT_ID, self::ITEM_ID); + $this->saveController->saveAction( + $this->formFactory, + $this->flashBag, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + $this->lockFlashMessageHelper, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testSaveActionIfNewCustomItemIsForbidden(): void @@ -353,7 +395,16 @@ public function testSaveActionIfNewCustomItemIsForbidden(): void $this->expectException(AccessDeniedHttpException::class); - $this->saveController->saveAction(self::OBJECT_ID); + $this->saveController->saveAction( + $this->formFactory, + $this->flashBag, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + $this->lockFlashMessageHelper, + self::OBJECT_ID + ); } public function testSaveActionForNewCustomItemWithInvalidForm(): void @@ -404,7 +455,16 @@ public function testSaveActionForNewCustomItemWithInvalidForm(): void $this->customItemModel->expects($this->never()) ->method('save'); - $this->saveController->saveAction(self::OBJECT_ID); + $this->saveController->saveAction( + $this->formFactory, + $this->flashBag, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + $this->lockFlashMessageHelper, + self::OBJECT_ID + ); } public function testSaveActionForNewCustomItemWithChildItemWhenInvalidForm(): void @@ -492,7 +552,16 @@ function (CustomItem $customItem) { $this->customItemModel->expects($this->never()) ->method('save'); - $this->saveController->saveAction(self::OBJECT_ID); + $this->saveController->saveAction( + $this->formFactory, + $this->flashBag, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + $this->lockFlashMessageHelper, + self::OBJECT_ID + ); } public function testSaveActionWhenTheItemIsLocked(): void @@ -512,21 +581,22 @@ public function testSaveActionWhenTheItemIsLocked(): void ->with($this->customItem) ->willReturn(true); - $userMock = $this->createMock(User::class); - $this->userHelper->expects($this->once()) - ->method('getUser') - ->willReturn($userMock); - - $userMock->expects($this->once()) - ->method('isAdmin') - ->willReturn(true); - $this->routeProvider->expects($this->once()) ->method('buildViewRoute') ->with(static::OBJECT_ID, static::ITEM_ID) ->willReturn('https://redirect.url'); - $this->saveController->saveAction(self::OBJECT_ID, self::ITEM_ID); + $this->saveController->saveAction( + $this->formFactory, + $this->flashBag, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + $this->lockFlashMessageHelper, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testThatUserIsGettingRedirectedWhenWeEditCustomItemAndContactIdIsSpecified(): void @@ -621,6 +691,16 @@ public function testThatUserIsGettingRedirectedWhenWeEditCustomItemAndContactIdI Assert::assertSame(Request::METHOD_GET, $this->request->getMethod()); - $this->saveController->saveAction(self::OBJECT_ID, self::ITEM_ID); + $this->saveController->saveAction( + $this->formFactory, + $this->flashBag, + $this->customItemModel, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + $this->lockFlashMessageHelper, + self::OBJECT_ID, + self::ITEM_ID + ); } } diff --git a/Tests/Unit/Controller/CustomItem/UnlinkControllerTest.php b/Tests/Unit/Controller/CustomItem/UnlinkControllerTest.php index 54376f4ff..c548accf1 100644 --- a/Tests/Unit/Controller/CustomItem/UnlinkControllerTest.php +++ b/Tests/Unit/Controller/CustomItem/UnlinkControllerTest.php @@ -15,7 +15,6 @@ use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; use PHPUnit\Framework\Assert; use PHPUnit\Framework\MockObject\MockObject; -use UnexpectedValueException; class UnlinkControllerTest extends ControllerTestCase { @@ -30,11 +29,6 @@ class UnlinkControllerTest extends ControllerTestCase */ private $customItemModel; - /** - * @var MockObject|FlashBag - */ - private $flashBag; - /** * @var MockObject|CustomItemPermissionProvider */ @@ -50,13 +44,8 @@ protected function setUp(): void parent::setUp(); $this->customItemModel = $this->createMock(CustomItemModel::class); - $this->flashBag = $this->createMock(FlashBag::class); $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); - $this->unlinkController = new UnlinkController( - $this->customItemModel, - $this->permissionProvider, - $this->flashBag - ); + $this->unlinkController = new UnlinkController(); $this->addSymfonyDependencies($this->unlinkController); } @@ -77,7 +66,14 @@ public function testSaveActionIfCustomItemNotFound(): void $this->customItemModel->expects($this->never()) ->method('unlinkEntity'); - $this->unlinkController->saveAction(self::ITEM_ID, self::ENTITY_TYPE, self::ENTITY_ID); + $this->unlinkController->saveAction( + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::ITEM_ID, + self::ENTITY_TYPE, + self::ENTITY_ID + ); } public function testSaveActionIfForbidden(): void @@ -100,7 +96,14 @@ public function testSaveActionIfForbidden(): void $this->customItemModel->expects($this->never()) ->method('unlinkEntity'); - $this->unlinkController->saveAction(self::ITEM_ID, self::ENTITY_TYPE, self::ENTITY_ID); + $this->unlinkController->saveAction( + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::ITEM_ID, + self::ENTITY_TYPE, + self::ENTITY_ID + ); } public function testSaveActionIfEntityTypeNotFound(): void @@ -111,19 +114,26 @@ public function testSaveActionIfEntityTypeNotFound(): void $this->customItemModel->expects($this->once()) ->method('unlinkEntity') - ->will($this->throwException(new UnexpectedValueException('Entity unicorn cannot be linked to a custom item'))); + ->will($this->throwException(new \UnexpectedValueException('Entity unicorn cannot be linked to a custom item'))); $this->flashBag->expects($this->once()) ->method('add') ->with('Entity unicorn cannot be linked to a custom item', [], FlashBag::LEVEL_ERROR); - $this->unlinkController->saveAction(self::ITEM_ID, 'unicorn', self::ENTITY_ID); + $this->unlinkController->saveAction( + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::ITEM_ID, + 'unicorn', + self::ENTITY_ID + ); } public function testSaveAction(): void { $customItem = new class(new CustomObject()) extends CustomItem { - public function getId() + public function getId(): int { return UnlinkControllerTest::ITEM_ID; } @@ -143,7 +153,14 @@ public function getId() $this->customItemModel->expects($this->never()) ->method('delete'); - $this->unlinkController->saveAction(self::ITEM_ID, self::ENTITY_TYPE, self::ENTITY_ID); + $this->unlinkController->saveAction( + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::ITEM_ID, + self::ENTITY_TYPE, + self::ENTITY_ID + ); } public function testSaveActionWithChildItem(): void @@ -157,7 +174,7 @@ public function testSaveActionWithChildItem(): void $customObject->setRelationshipObject($childCustomObject); $customItem = new class($customObject) extends CustomItem { - public function getId() + public function getId(): int { return UnlinkControllerTest::ITEM_ID; } @@ -190,6 +207,13 @@ function (CustomItem $childCustomItem) use ($childCustomObject) { } )); - $this->unlinkController->saveAction(self::ITEM_ID, self::ENTITY_TYPE, self::ENTITY_ID); + $this->unlinkController->saveAction( + $this->customItemModel, + $this->permissionProvider, + $this->flashBag, + self::ITEM_ID, + self::ENTITY_TYPE, + self::ENTITY_ID + ); } } diff --git a/Tests/Unit/Controller/CustomItem/ViewControllerTest.php b/Tests/Unit/Controller/CustomItem/ViewControllerTest.php index e8ea8b4e1..c2e0ed8df 100644 --- a/Tests/Unit/Controller/CustomItem/ViewControllerTest.php +++ b/Tests/Unit/Controller/CustomItem/ViewControllerTest.php @@ -17,9 +17,11 @@ use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormInterface; -use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\ParameterBag; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +#[\AllowDynamicProperties] class ViewControllerTest extends ControllerTestCase { private const OBJECT_ID = 33; @@ -49,18 +51,25 @@ protected function setUp(): void $this->auditLog = $this->createMock(AuditLogModel::class); $this->permissionProvider = $this->createMock(CustomItemPermissionProvider::class); $this->routeProvider = $this->createMock(CustomItemRouteProvider::class); - $this->requestStack = $this->createMock(RequestStack::class); $this->formFactory = $this->createMock(FormFactoryInterface::class); $this->form = $this->createMock(FormInterface::class); $this->customItem = $this->createMock(CustomItem::class); + $this->request = $this->createMock(Request::class); + $this->requestStack->expects($this->any()) + ->method('getCurrentRequest') + ->willReturn($this->request); + $this->viewController = new ViewController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, + $this->flashBag, $this->requestStack, - $this->formFactory, - $this->customItemModel, - $this->customItemXrefContactModel, - $this->auditLog, - $this->permissionProvider, - $this->routeProvider + $this->security ); $this->addSymfonyDependencies($this->viewController); @@ -78,7 +87,22 @@ public function testViewActionIfCustomItemNotFound(): void $this->routeProvider->expects($this->never()) ->method('buildViewRoute'); - $this->viewController->viewAction(self::OBJECT_ID, self::ITEM_ID); + $post = $this->createMock(ParameterBag::class); + $this->request->request = $post; + $post->expects($this->once()) + ->method('all') + ->willReturn([]); + + $this->viewController->viewAction( + $this->formFactory, + $this->customItemModel, + $this->customItemXrefContactModel, + $this->auditLog, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testViewActionIfCustomItemForbidden(): void @@ -94,9 +118,22 @@ public function testViewActionIfCustomItemForbidden(): void $this->routeProvider->expects($this->never()) ->method('buildViewRoute'); + $this->security->expects($this->once()) + ->method('isAnonymous') + ->willReturn(true); + $this->expectException(AccessDeniedHttpException::class); - $this->viewController->viewAction(self::OBJECT_ID, self::ITEM_ID); + $this->viewController->viewAction( + $this->formFactory, + $this->customItemModel, + $this->customItemXrefContactModel, + $this->auditLog, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } public function testViewAction(): void @@ -154,6 +191,15 @@ public function testViewAction(): void ->method('getLogForObject') ->with('customItem', self::ITEM_ID, '2019-01-04 10:20:30', 10, 'customObjects'); - $this->viewController->viewAction(self::OBJECT_ID, self::ITEM_ID); + $this->viewController->viewAction( + $this->formFactory, + $this->customItemModel, + $this->customItemXrefContactModel, + $this->auditLog, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID, + self::ITEM_ID + ); } } diff --git a/Tests/Unit/Controller/CustomObject/CancelControllerTest.php b/Tests/Unit/Controller/CustomObject/CancelControllerTest.php index 3e1c8b628..3d6cc3ae7 100644 --- a/Tests/Unit/Controller/CustomObject/CancelControllerTest.php +++ b/Tests/Unit/Controller/CustomObject/CancelControllerTest.php @@ -22,24 +22,32 @@ class CancelControllerTest extends ControllerTestCase * @var CancelController */ private $cancelController; + private $sessionProviderFactory; protected function setUp(): void { parent::setUp(); - $sessionProviderFactory = $this->createMock(SessionProviderFactory::class); - $this->sessionProvider = $this->createMock(SessionProvider::class); - $this->routeProvider = $this->createMock(CustomObjectRouteProvider::class); - $this->customObjectModel = $this->createMock(CustomObjectModel::class); + $this->sessionProviderFactory = $this->createMock(SessionProviderFactory::class); + $this->sessionProvider = $this->createMock(SessionProvider::class); + $this->routeProvider = $this->createMock(CustomObjectRouteProvider::class); + $this->customObjectModel = $this->createMock(CustomObjectModel::class); $this->cancelController = new CancelController( - $sessionProviderFactory, - $this->routeProvider, - $this->customObjectModel + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, + $this->flashBag, + $this->requestStack, + $this->security ); $this->addSymfonyDependencies($this->cancelController); - $sessionProviderFactory->method('createObjectProvider')->willReturn($this->sessionProvider); + $this->sessionProviderFactory->method('createObjectProvider')->willReturn($this->sessionProvider); } public function testCancelAction(): void @@ -58,7 +66,12 @@ public function testCancelAction(): void ->with($pageNumber) ->willReturn('some/route'); - $this->cancelController->cancelAction(null); + $this->cancelController->cancelAction( + $this->sessionProviderFactory, + $this->routeProvider, + $this->customObjectModel, + null + ); } public function testCancelActionWithEntityUnlock(): void @@ -85,6 +98,11 @@ public function testCancelActionWithEntityUnlock(): void ->with($pageNumber) ->willReturn('some/route'); - $this->cancelController->cancelAction($customObjectId); + $this->cancelController->cancelAction( + $this->sessionProviderFactory, + $this->routeProvider, + $this->customObjectModel, + $customObjectId + ); } } diff --git a/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php b/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php index e5bb892fd..6004f4c23 100644 --- a/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php +++ b/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php @@ -5,7 +5,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\CustomObject; use Doctrine\Common\Collections\ArrayCollection; -use Mautic\CoreBundle\Service\FlashBag; use Mautic\LeadBundle\Entity\LeadList; use MauticPlugin\CustomObjectsBundle\Controller\CustomObject\DeleteController; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; @@ -17,10 +16,9 @@ use MauticPlugin\CustomObjectsBundle\Provider\SessionProvider; use MauticPlugin\CustomObjectsBundle\Provider\SessionProviderFactory; use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; -use Symfony\Component\Translation\TranslatorInterface; class DeleteControllerTest extends ControllerTestCase { @@ -28,56 +26,52 @@ class DeleteControllerTest extends ControllerTestCase private $customObjectModel; private $sessionProvider; - private $flashBag; - private $permissionProvider; - /** - * @var EventDispatcherInterface - */ - private $eventDispatcher; + private $permissionProvider; /** * @var DeleteController */ private $deleteController; - /** - * @var TranslatorInterface - */ - private $translator; - /** * @var int */ private $leadListIndex; + private $sessionProviderFactory; protected function setUp(): void { parent::setUp(); - $sessionProviderFactory = $this->createMock(SessionProviderFactory::class); - $this->customObjectModel = $this->createMock(CustomObjectModel::class); - $this->sessionProvider = $this->createMock(SessionProvider::class); - $this->flashBag = $this->createMock(FlashBag::class); - $this->permissionProvider = $this->createMock(CustomObjectPermissionProvider::class); - $this->request = $this->createMock(Request::class); - $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); + $this->sessionProviderFactory = $this->createMock(SessionProviderFactory::class); + $this->customObjectModel = $this->createMock(CustomObjectModel::class); + $this->sessionProvider = $this->createMock(SessionProvider::class); + $this->permissionProvider = $this->createMock(CustomObjectPermissionProvider::class); + $this->request = $this->createMock(Request::class); + + $this->requestStack->expects($this->any()) + ->method('getCurrentRequest') + ->willReturn($this->request); + $this->deleteController = new DeleteController( - $this->customObjectModel, - $sessionProviderFactory, + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, $this->flashBag, - $this->permissionProvider, - $this->eventDispatcher + $this->requestStack, + $this->security ); $this->addSymfonyDependencies($this->deleteController); $this->request->method('isXmlHttpRequest')->willReturn(true); $this->request->method('getRequestUri')->willReturn('https://a.b'); - $sessionProviderFactory->method('createObjectProvider')->willReturn($this->sessionProvider); - - $this->translator = $this->createMock(TranslatorInterface::class); - $this->deleteController->setTranslator($this->translator); + $this->sessionProviderFactory->method('createObjectProvider')->willReturn($this->sessionProvider); $this->leadListIndex = 1; } @@ -94,7 +88,20 @@ public function testDeleteActionIfCustomObjectNotFound(): void $this->flashBag->expects($this->never()) ->method('add'); - $this->deleteController->deleteAction(self::OBJECT_ID); + $post = $this->createMock(ParameterBag::class); + $this->request->request = $post; + $post->expects($this->once()) + ->method('all') + ->willReturn([]); + + $this->deleteController->deleteAction( + $this->sessionProviderFactory, + $this->customObjectModel, + $this->flashBag, + $this->permissionProvider, + $this->dispatcher, + self::OBJECT_ID + ); } public function testDeleteActionIfCustomObjectForbidden(): void @@ -113,9 +120,20 @@ public function testDeleteActionIfCustomObjectForbidden(): void $this->flashBag->expects($this->never()) ->method('add'); + $this->security->expects($this->once()) + ->method('isAnonymous') + ->willReturn(true); + $this->expectException(AccessDeniedHttpException::class); - $this->deleteController->deleteAction(self::OBJECT_ID); + $this->deleteController->deleteAction( + $this->sessionProviderFactory, + $this->customObjectModel, + $this->flashBag, + $this->permissionProvider, + $this->dispatcher, + self::OBJECT_ID + ); } public function testDeleteAction(): void @@ -129,14 +147,21 @@ public function testDeleteAction(): void ->with(self::OBJECT_ID) ->willReturn($customObject); - $this->eventDispatcher->expects($this->once()) + $this->dispatcher->expects($this->once()) ->method('dispatch'); $this->sessionProvider->expects($this->once()) ->method('getPage') ->willReturn(3); - $this->deleteController->deleteAction(self::OBJECT_ID); + $this->deleteController->deleteAction( + $this->sessionProviderFactory, + $this->customObjectModel, + $this->flashBag, + $this->permissionProvider, + $this->dispatcher, + self::OBJECT_ID + ); } public function testThatItDisplaysErrorMessageIfThereAreRelatedSegments(): void @@ -150,7 +175,7 @@ public function testThatItDisplaysErrorMessageIfThereAreRelatedSegments(): void ->with(self::OBJECT_ID) ->willReturn($customObject); - $this->eventDispatcher->expects($this->never()) + $this->dispatcher->expects($this->never()) ->method('dispatch'); $this->flashBag->expects($this->once()) @@ -168,7 +193,14 @@ public function testThatItDisplaysErrorMessageIfThereAreRelatedSegments(): void ->method('checkIfTheCustomObjectIsUsedInSegmentFilters') ->willThrowException($inUseException); - $this->deleteController->deleteAction(self::OBJECT_ID); + $this->deleteController->deleteAction( + $this->sessionProviderFactory, + $this->customObjectModel, + $this->flashBag, + $this->permissionProvider, + $this->dispatcher, + self::OBJECT_ID + ); } private function createSegments(int $quantity): ArrayCollection diff --git a/Tests/Unit/Controller/CustomObject/FormControllerTest.php b/Tests/Unit/Controller/CustomObject/FormControllerTest.php index 2d1fd8943..04b26c651 100644 --- a/Tests/Unit/Controller/CustomObject/FormControllerTest.php +++ b/Tests/Unit/Controller/CustomObject/FormControllerTest.php @@ -4,6 +4,7 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\CustomObject; +use Mautic\CoreBundle\Model\NotificationModel; use MauticPlugin\CustomObjectsBundle\Controller\CustomObject\FormController; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Exception\ForbiddenException; @@ -18,9 +19,11 @@ use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; use Symfony\Component\Form\FormFactory; use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +#[\AllowDynamicProperties] class FormControllerTest extends ControllerTestCase { private const OBJECT_ID = 33; @@ -54,14 +57,19 @@ protected function setUp(): void $this->request = $this->createMock(Request::class); $this->customObject = $this->createMock(CustomObject::class); $this->form = $this->createMock(FormInterface::class); - $this->formController = new FormController( - $this->formFactory, - $this->customObjectModel, - $this->customFieldModel, - $this->permissionProvider, - $this->routeProvider, - $this->customFieldTypeProvider, - $this->lockFlashMessageHelper + $this->model = $this->createMock(NotificationModel::class); + + $this->formController = new FormController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, + $this->flashBag, + $this->requestStack, + $this->security ); $this->addSymfonyDependencies($this->formController); @@ -82,7 +90,13 @@ public function testNewActionIfForbidden(): void $this->expectException(AccessDeniedHttpException::class); - $this->formController->newAction(); + $this->formController->newAction( + $this->permissionProvider, + $this->formFactory, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->customFieldModel + ); } public function testNewAction(): void @@ -110,7 +124,21 @@ public function testNewAction(): void ->method('buildSaveRoute') ->willReturn('https://list.items'); - $this->formController->newAction(); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->formController->newAction( + $this->permissionProvider, + $this->formFactory, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->customFieldModel + ); } public function testEditActionIfCustomObjectNotFound(): void @@ -123,7 +151,22 @@ public function testEditActionIfCustomObjectNotFound(): void $this->routeProvider->expects($this->never()) ->method('buildEditRoute'); - $this->formController->editAction(self::OBJECT_ID); + $post = $this->createMock(ParameterBag::class); + $this->request->request = $post; + $post->expects($this->once()) + ->method('all') + ->willReturn([]); + + $this->formController->editAction( + $this->customObjectModel, + $this->permissionProvider, + $this->lockFlashMessageHelper, + $this->formFactory, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->customFieldModel, + self::OBJECT_ID + ); } public function testEditActionIfCustomObjectForbidden(): void @@ -142,7 +185,16 @@ public function testEditActionIfCustomObjectForbidden(): void $this->expectException(AccessDeniedHttpException::class); - $this->formController->editAction(self::OBJECT_ID); + $this->formController->editAction( + $this->customObjectModel, + $this->permissionProvider, + $this->lockFlashMessageHelper, + $this->formFactory, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->customFieldModel, + self::OBJECT_ID + ); } public function testEditAction(): void @@ -188,7 +240,24 @@ public function testEditAction(): void ->with(self::OBJECT_ID) ->willReturn('https://list.items'); - $this->formController->editAction(self::OBJECT_ID); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->formController->editAction( + $this->customObjectModel, + $this->permissionProvider, + $this->lockFlashMessageHelper, + $this->formFactory, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->customFieldModel, + self::OBJECT_ID + ); } public function testCloneActionIfCustomObjectNotFound(): void @@ -201,7 +270,21 @@ public function testCloneActionIfCustomObjectNotFound(): void $this->routeProvider->expects($this->never()) ->method('buildCloneRoute'); - $this->formController->cloneAction(self::OBJECT_ID); + $post = $this->createMock(ParameterBag::class); + $this->request->request = $post; + $post->expects($this->once()) + ->method('all') + ->willReturn([]); + + $this->formController->cloneAction( + $this->customObjectModel, + $this->permissionProvider, + $this->formFactory, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->customFieldModel, + self::OBJECT_ID + ); } public function testCloneActionIfCustomObjectForbidden(): void @@ -220,7 +303,15 @@ public function testCloneActionIfCustomObjectForbidden(): void $this->expectException(AccessDeniedHttpException::class); - $this->formController->cloneAction(self::OBJECT_ID); + $this->formController->cloneAction( + $this->customObjectModel, + $this->permissionProvider, + $this->formFactory, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->customFieldModel, + self::OBJECT_ID + ); } public function testCloneAction(): void @@ -252,6 +343,22 @@ public function testCloneAction(): void ->method('buildSaveRoute') ->willReturn('https://list.items'); - $this->formController->cloneAction(self::OBJECT_ID); + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->modelFactory->expects($this->once()) + ->method('getModel') + ->willReturn($this->model); + + $this->formController->cloneAction( + $this->customObjectModel, + $this->permissionProvider, + $this->formFactory, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->customFieldModel, + self::OBJECT_ID + ); } } diff --git a/Tests/Unit/Controller/CustomObject/ListControllerTest.php b/Tests/Unit/Controller/CustomObject/ListControllerTest.php index c346ac8bd..0991fa819 100644 --- a/Tests/Unit/Controller/CustomObject/ListControllerTest.php +++ b/Tests/Unit/Controller/CustomObject/ListControllerTest.php @@ -16,9 +16,9 @@ use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +#[\AllowDynamicProperties] class ListControllerTest extends ControllerTestCase { private const PAGE = 3; @@ -37,25 +37,29 @@ protected function setUp(): void { parent::setUp(); - $sessionProviderFactory = $this->createMock(SessionProviderFactory::class); - $this->requestStack = $this->createMock(RequestStack::class); - $this->customObjectModel = $this->createMock(CustomObjectModel::class); - $this->sessionProvider = $this->createMock(SessionProvider::class); - $this->permissionProvider = $this->createMock(CustomObjectPermissionProvider::class); - $this->routeProvider = $this->createMock(CustomObjectRouteProvider::class); - $this->request = $this->createMock(Request::class); - $this->listController = new ListController( + $this->sessionProviderFactory = $this->createMock(SessionProviderFactory::class); + $this->customObjectModel = $this->createMock(CustomObjectModel::class); + $this->sessionProvider = $this->createMock(SessionProvider::class); + $this->permissionProvider = $this->createMock(CustomObjectPermissionProvider::class); + $this->routeProvider = $this->createMock(CustomObjectRouteProvider::class); + $this->request = $this->createMock(Request::class); + $this->listController = new ListController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, + $this->flashBag, $this->requestStack, - $sessionProviderFactory, - $this->customObjectModel, - $this->permissionProvider, - $this->routeProvider + $this->security ); $this->addSymfonyDependencies($this->listController); $this->requestStack->method('getCurrentRequest')->willReturn($this->request); - $sessionProviderFactory->method('createObjectProvider')->willReturn($this->sessionProvider); + $this->sessionProviderFactory->method('createObjectProvider')->willReturn($this->sessionProvider); } public function testListActionIfForbidden(): void @@ -69,7 +73,13 @@ public function testListActionIfForbidden(): void $this->expectException(AccessDeniedHttpException::class); - $this->listController->listAction(self::PAGE); + $this->listController->listAction( + $this->sessionProviderFactory, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + self::PAGE + ); } public function testListAction(): void @@ -123,7 +133,13 @@ public function testListAction(): void ->method('setPageLimit') ->with($pageLimit); - $this->listController->listAction(self::PAGE); + $this->listController->listAction( + $this->sessionProviderFactory, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + self::PAGE + ); } public function testListActionWithOrderByQueryParamAndAjax(): void @@ -189,6 +205,16 @@ public function testListActionWithOrderByQueryParamAndAjax(): void ->method('setPageLimit') ->with($pageLimit); - $this->listController->listAction(self::PAGE); + $this->sessionProvider->expects($this->once()) + ->method('setPageLimit') + ->with($pageLimit); + + $this->listController->listAction( + $this->sessionProviderFactory, + $this->customObjectModel, + $this->permissionProvider, + $this->routeProvider, + self::PAGE + ); } } diff --git a/Tests/Unit/Controller/CustomObject/SaveControllerTest.php b/Tests/Unit/Controller/CustomObject/SaveControllerTest.php index a70329db8..543606df1 100644 --- a/Tests/Unit/Controller/CustomObject/SaveControllerTest.php +++ b/Tests/Unit/Controller/CustomObject/SaveControllerTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\CustomObject; -use Mautic\CoreBundle\Service\FlashBag; use MauticPlugin\CustomObjectsBundle\Controller\CustomObject\SaveController; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Exception\ForbiddenException; @@ -23,10 +22,11 @@ use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +#[\AllowDynamicProperties] class SaveControllerTest extends ControllerTestCase { private const OBJECT_ID = 33; @@ -37,7 +37,6 @@ class SaveControllerTest extends ControllerTestCase private $customFieldTypeProvider; private $paramsToStringTransformer; private $optionsToStringTransformer; - private $flashBag; private $permissionProvider; private $routeProvider; private $lockFlashMessageHelper; @@ -56,10 +55,8 @@ protected function setUp(): void $this->formFactory = $this->createMock(FormFactoryInterface::class); $this->customObjectModel = $this->createMock(CustomObjectModel::class); $this->customFieldModel = $this->createMock(CustomFieldModel::class); - $this->flashBag = $this->createMock(FlashBag::class); $this->permissionProvider = $this->createMock(CustomObjectPermissionProvider::class); $this->routeProvider = $this->createMock(CustomObjectRouteProvider::class); - $this->requestStack = $this->createMock(RequestStack::class); $this->customFieldTypeProvider = $this->createMock(CustomFieldTypeProvider::class); $this->paramsToStringTransformer = $this->createMock(ParamsToStringTransformer::class); $this->optionsToStringTransformer = $this->createMock(OptionsToStringTransformer::class); @@ -67,21 +64,25 @@ protected function setUp(): void $this->request = $this->createMock(Request::class); $this->customObject = $this->createMock(CustomObject::class); $this->form = $this->createMock(FormInterface::class); + $this->saveController = new SaveController( - $this->requestStack, + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, $this->flashBag, - $this->formFactory, - $this->customObjectModel, - $this->customFieldModel, - $this->permissionProvider, - $this->routeProvider, - $this->customFieldTypeProvider, - $this->paramsToStringTransformer, - $this->optionsToStringTransformer, - $this->lockFlashMessageHelper + $this->requestStack, + $this->security ); $this->addSymfonyDependencies($this->saveController); + + $this->requestStack->expects($this->any()) + ->method('getCurrentRequest') + ->willReturn($this->request); } public function testSaveActionIfExistingCustomObjectNotFound(): void @@ -96,7 +97,25 @@ public function testSaveActionIfExistingCustomObjectNotFound(): void $this->permissionProvider->expects($this->never()) ->method('canCreate'); - $this->saveController->saveAction(self::OBJECT_ID); + $post = $this->createMock(ParameterBag::class); + $this->request->request = $post; + $post->expects($this->once()) + ->method('all') + ->willReturn([]); + + $this->saveController->saveAction( + $this->flashBag, + $this->formFactory, + $this->customObjectModel, + $this->customFieldModel, + $this->permissionProvider, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->paramsToStringTransformer, + $this->optionsToStringTransformer, + $this->lockFlashMessageHelper, + self::OBJECT_ID + ); } public function testSaveActionIfExistingCustomObjectIsForbidden(): void @@ -114,7 +133,19 @@ public function testSaveActionIfExistingCustomObjectIsForbidden(): void $this->expectException(AccessDeniedHttpException::class); - $this->saveController->saveAction(self::OBJECT_ID); + $this->saveController->saveAction( + $this->flashBag, + $this->formFactory, + $this->customObjectModel, + $this->customFieldModel, + $this->permissionProvider, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->paramsToStringTransformer, + $this->optionsToStringTransformer, + $this->lockFlashMessageHelper, + self::OBJECT_ID + ); } public function testSaveActionForExistingCustomObjectWithValidFormClickingApply(): void @@ -196,7 +227,19 @@ public function testSaveActionForExistingCustomObjectWithValidFormClickingApply( ->with('custom_object') ->willReturn([]); - $this->saveController->saveAction(self::OBJECT_ID); + $this->saveController->saveAction( + $this->flashBag, + $this->formFactory, + $this->customObjectModel, + $this->customFieldModel, + $this->permissionProvider, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->paramsToStringTransformer, + $this->optionsToStringTransformer, + $this->lockFlashMessageHelper, + self::OBJECT_ID + ); } public function testSaveActionForExistingCustomObjectWithValidFormClickingSaveAndAjax(): void @@ -298,7 +341,19 @@ public function testSaveActionForExistingCustomObjectWithValidFormClickingSaveAn ->willReturn([]); /** @var JsonResponse $jsonResponse */ - $jsonResponse = $this->saveController->saveAction(self::OBJECT_ID); + $jsonResponse = $this->saveController->saveAction( + $this->flashBag, + $this->formFactory, + $this->customObjectModel, + $this->customFieldModel, + $this->permissionProvider, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->paramsToStringTransformer, + $this->optionsToStringTransformer, + $this->lockFlashMessageHelper, + self::OBJECT_ID + ); $this->assertMatchesRegularExpression('/Redirecting to https:\/\/view.object/', $jsonResponse->getContent()); } @@ -352,6 +407,17 @@ public function testSaveActionForNewCustomObjectWithInvalidForm(): void $this->customFieldTypeProvider->expects($this->once()) ->method('getTypes'); - $this->saveController->saveAction(); + $this->saveController->saveAction( + $this->flashBag, + $this->formFactory, + $this->customObjectModel, + $this->customFieldModel, + $this->permissionProvider, + $this->routeProvider, + $this->customFieldTypeProvider, + $this->paramsToStringTransformer, + $this->optionsToStringTransformer, + $this->lockFlashMessageHelper, + ); } } diff --git a/Tests/Unit/Controller/CustomObject/ViewControllerTest.php b/Tests/Unit/Controller/CustomObject/ViewControllerTest.php index b86f4faee..1e1130358 100644 --- a/Tests/Unit/Controller/CustomObject/ViewControllerTest.php +++ b/Tests/Unit/Controller/CustomObject/ViewControllerTest.php @@ -16,9 +16,12 @@ use MauticPlugin\CustomObjectsBundle\Tests\Unit\Controller\ControllerTestCase; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpFoundation\ParameterBag; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +#[\AllowDynamicProperties] class ViewControllerTest extends ControllerTestCase { private const OBJECT_ID = 33; @@ -45,19 +48,29 @@ protected function setUp(): void $this->permissionProvider = $this->createMock(CustomObjectPermissionProvider::class); $this->routeProvider = $this->createMock(CustomObjectRouteProvider::class); $this->requestStack = $this->createMock(RequestStack::class); + $this->request = $this->createMock(Request::class); $this->formFactory = $this->createMock(FormFactoryInterface::class); $this->form = $this->createMock(FormInterface::class); $this->customObject = $this->createMock(CustomObject::class); + $this->viewController = new ViewController( + $this->managerRegistry, + $this->mauticFactory, + $this->modelFactory, + $this->userHelper, + $this->coreParametersHelper, + $this->dispatcher, + $this->translator, + $this->flashBag, $this->requestStack, - $this->formFactory, - $this->customObjectModel, - $this->auditLog, - $this->permissionProvider, - $this->routeProvider + $this->security ); $this->addSymfonyDependencies($this->viewController); + + $this->requestStack->expects($this->any()) + ->method('getCurrentRequest') + ->willReturn($this->request); } public function testViewActionIfCustomObjectNotFound(): void @@ -72,7 +85,20 @@ public function testViewActionIfCustomObjectNotFound(): void $this->routeProvider->expects($this->never()) ->method('buildViewRoute'); - $this->viewController->viewAction(self::OBJECT_ID); + $post = $this->createMock(ParameterBag::class); + $this->request->request = $post; + $post->expects($this->once()) + ->method('all') + ->willReturn([]); + + $this->viewController->viewAction( + $this->formFactory, + $this->customObjectModel, + $this->auditLog, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID + ); } public function testViewActionIfCustomObjectForbidden(): void @@ -88,9 +114,20 @@ public function testViewActionIfCustomObjectForbidden(): void $this->routeProvider->expects($this->never()) ->method('buildViewRoute'); + $this->security->expects($this->once()) + ->method('isAnonymous') + ->willReturn(true); + $this->expectException(AccessDeniedHttpException::class); - $this->viewController->viewAction(self::OBJECT_ID); + $this->viewController->viewAction( + $this->formFactory, + $this->customObjectModel, + $this->auditLog, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID + ); } public function testViewAction(): void @@ -148,6 +185,13 @@ public function testViewAction(): void ->method('getLogForObject') ->with('customObject', self::OBJECT_ID, '2019-01-04 10:20:30', 10, 'customObjects'); - $this->viewController->viewAction(self::OBJECT_ID); + $this->viewController->viewAction( + $this->formFactory, + $this->customObjectModel, + $this->auditLog, + $this->permissionProvider, + $this->routeProvider, + self::OBJECT_ID + ); } } diff --git a/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php b/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php index 37a9c8908..31246ecd4 100644 --- a/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php +++ b/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php @@ -9,7 +9,7 @@ use MauticPlugin\CustomObjectsBundle\CustomFieldType\EmailType; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Exception\UndefinedTransformerException; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class AbstractCustomFieldTypeTest extends \PHPUnit\Framework\TestCase { @@ -26,8 +26,6 @@ protected function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); - $this->translator = $this->createMock(TranslatorInterface::class); $this->customField = $this->createMock(CustomField::class); $this->filterOperatorProvider = $this->createMock(FilterOperatorProviderInterface::class); diff --git a/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php b/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php index d5bae2109..4702d613b 100644 --- a/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php +++ b/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php @@ -16,7 +16,7 @@ use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; use MauticPlugin\CustomObjectsBundle\Helper\CsvHelper; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class AbstractMultivalueTypeTest extends \PHPUnit\Framework\TestCase { @@ -80,7 +80,7 @@ public function testGetOperators(): void 'in' => [], '!in' => [], 'somethingelse' => [], - ]); + ]); $operators = $this->fieldType->getOperators(); diff --git a/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php b/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php index f57dd097f..1abaedda2 100644 --- a/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php +++ b/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php @@ -10,7 +10,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomFieldValueText; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use Symfony\Component\Form\Extension\Core\Type\TextType; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class AbstractTextTypeTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/CustomFieldType/CountryTypeTest.php b/Tests/Unit/CustomFieldType/CountryTypeTest.php index 5b76ce15f..674115143 100644 --- a/Tests/Unit/CustomFieldType/CountryTypeTest.php +++ b/Tests/Unit/CustomFieldType/CountryTypeTest.php @@ -8,7 +8,7 @@ use MauticPlugin\CustomObjectsBundle\CustomFieldType\CountryType; use MauticPlugin\CustomObjectsBundle\Entity\CustomFieldValueText; use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CountryTypeTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/CustomFieldType/DataTransformer/DateTimeAtomTransformerTest.php b/Tests/Unit/CustomFieldType/DataTransformer/DateTimeAtomTransformerTest.php index 7faebafad..90dec29af 100644 --- a/Tests/Unit/CustomFieldType/DataTransformer/DateTimeAtomTransformerTest.php +++ b/Tests/Unit/CustomFieldType/DataTransformer/DateTimeAtomTransformerTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\CustomFieldType\DataTransformer; -use DateTime; use MauticPlugin\CustomObjectsBundle\CustomFieldType\DataTransformer\DateTimeAtomTransformer; class DateTimeAtomTransformerTest extends \PHPUnit\Framework\TestCase @@ -12,7 +11,7 @@ class DateTimeAtomTransformerTest extends \PHPUnit\Framework\TestCase public function test(): void { $date = '2019-05-30T13:45:04+00:00'; - $datetime = new DateTime($date); + $datetime = new \DateTime($date); $format = DATE_ATOM; $transformer = new DateTimeAtomTransformer(); diff --git a/Tests/Unit/CustomFieldType/DateTimeTypeTest.php b/Tests/Unit/CustomFieldType/DateTimeTypeTest.php index f9ecf679d..3f4f92227 100644 --- a/Tests/Unit/CustomFieldType/DateTimeTypeTest.php +++ b/Tests/Unit/CustomFieldType/DateTimeTypeTest.php @@ -13,7 +13,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomFieldValueDateTime; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Exception\InvalidValueException; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class DateTimeTypeTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/CustomFieldType/DateTypeTest.php b/Tests/Unit/CustomFieldType/DateTypeTest.php index 2458f4ba7..b18ebed52 100644 --- a/Tests/Unit/CustomFieldType/DateTypeTest.php +++ b/Tests/Unit/CustomFieldType/DateTypeTest.php @@ -12,7 +12,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomFieldValueDate; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Exception\InvalidValueException; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class DateTypeTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/CustomFieldType/EmailTypeTest.php b/Tests/Unit/CustomFieldType/EmailTypeTest.php index 94f9f347f..25138fc92 100644 --- a/Tests/Unit/CustomFieldType/EmailTypeTest.php +++ b/Tests/Unit/CustomFieldType/EmailTypeTest.php @@ -7,7 +7,7 @@ use Mautic\LeadBundle\Provider\FilterOperatorProviderInterface; use MauticPlugin\CustomObjectsBundle\CustomFieldType\EmailType; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class EmailTypeTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/CustomFieldType/IntTypeTest.php b/Tests/Unit/CustomFieldType/IntTypeTest.php index 92f21ca1b..8273c63ec 100644 --- a/Tests/Unit/CustomFieldType/IntTypeTest.php +++ b/Tests/Unit/CustomFieldType/IntTypeTest.php @@ -9,7 +9,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomFieldValueInt; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class IntTypeTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/CustomFieldType/MultiselectTypeTest.php b/Tests/Unit/CustomFieldType/MultiselectTypeTest.php index 5df503b17..7c02fe404 100644 --- a/Tests/Unit/CustomFieldType/MultiselectTypeTest.php +++ b/Tests/Unit/CustomFieldType/MultiselectTypeTest.php @@ -7,7 +7,7 @@ use Mautic\LeadBundle\Provider\FilterOperatorProviderInterface; use MauticPlugin\CustomObjectsBundle\CustomFieldType\MultiselectType; use MauticPlugin\CustomObjectsBundle\Helper\CsvHelper; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class MultiselectTypeTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/CustomFieldType/PhoneTypeTest.php b/Tests/Unit/CustomFieldType/PhoneTypeTest.php index 941baf036..eb090d12f 100644 --- a/Tests/Unit/CustomFieldType/PhoneTypeTest.php +++ b/Tests/Unit/CustomFieldType/PhoneTypeTest.php @@ -7,7 +7,7 @@ use Mautic\LeadBundle\Provider\FilterOperatorProviderInterface; use MauticPlugin\CustomObjectsBundle\CustomFieldType\PhoneType; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class PhoneTypeTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/CustomFieldType/SelectTypeTest.php b/Tests/Unit/CustomFieldType/SelectTypeTest.php index a1096a022..ae118df29 100644 --- a/Tests/Unit/CustomFieldType/SelectTypeTest.php +++ b/Tests/Unit/CustomFieldType/SelectTypeTest.php @@ -11,7 +11,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class SelectTypeTest extends \PHPUnit\Framework\TestCase { @@ -60,7 +60,7 @@ public function testGetOperators(): void '=' => [], '!=' => [], 'somethingelse' => [], - ]); + ]); $operators = $this->fieldType->getOperators(); diff --git a/Tests/Unit/CustomFieldType/UrlTypeTest.php b/Tests/Unit/CustomFieldType/UrlTypeTest.php index fdaa75929..1a617c73f 100644 --- a/Tests/Unit/CustomFieldType/UrlTypeTest.php +++ b/Tests/Unit/CustomFieldType/UrlTypeTest.php @@ -7,7 +7,7 @@ use Mautic\LeadBundle\Provider\FilterOperatorProviderInterface; use MauticPlugin\CustomObjectsBundle\CustomFieldType\UrlType; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class UrlTypeTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/CustomObjectTestCase.php b/Tests/Unit/CustomObjectTestCase.php index 39809599a..d31014eaf 100644 --- a/Tests/Unit/CustomObjectTestCase.php +++ b/Tests/Unit/CustomObjectTestCase.php @@ -4,8 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit; -use DateTimeImmutable; -use DateTimeZone; use Mautic\CoreBundle\Test\MauticMysqlTestCase; use Mautic\LeadBundle\Entity\Lead; use Mautic\UserBundle\Entity\User; @@ -62,7 +60,7 @@ protected function createContact(string $firstName = 'name', string $lastName = protected function createCustomItemExportScheduleEntity(CustomObject $customObject): CustomItemExportScheduler { $customItemExportScheduler = new CustomItemExportScheduler(); - $customItemExportScheduler->setScheduledDateTime(new DateTimeImmutable('now', new DateTimeZone('UTC'))); + $customItemExportScheduler->setScheduledDateTime(new \DateTimeImmutable('now', new \DateTimeZone('UTC'))); $customItemExportScheduler->setUser($this->em->getRepository(User::class)->find(1)); $customItemExportScheduler->setCustomObjectId((int) $customObject->getId()); diff --git a/Tests/Unit/Entity/CustomFieldTest.php b/Tests/Unit/Entity/CustomFieldTest.php index cc44dd05d..4e9f3a9b8 100644 --- a/Tests/Unit/Entity/CustomFieldTest.php +++ b/Tests/Unit/Entity/CustomFieldTest.php @@ -19,13 +19,13 @@ use MauticPlugin\CustomObjectsBundle\Form\Validator\Constraints\AllowUniqueIdentifier; use MauticPlugin\CustomObjectsBundle\Helper\CsvHelper; use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomFieldTest extends \PHPUnit\Framework\TestCase { @@ -282,8 +282,8 @@ public function testGetChoices(): void ); $this->assertSame([ - 'Option A label' => 'option_a_value', - 'Option B label' => 'option_b_value', + 'Option A label' => 'option_a_value', + 'Option B label' => 'option_b_value', ], $customField->getChoices()); } @@ -316,6 +316,22 @@ public function testValueToLabel(): void $this->assertSame('Option B', $customField->valueToLabel('option_b')); } + public function testValueToLabelWithInteger(): void + { + $customField = new CustomField(); + $optionB = new CustomFieldOption(); + $optionB->setLabel('1'); + $optionB->setValue('1'); + $customField->addOption($optionB); + $customField->setTypeObject( + new SelectType( + $this->createMock(TranslatorInterface::class), + $this->createMock(FilterOperatorProviderInterface::class) + ) + ); + $this->assertSame('1', $customField->valueToLabel('1')); + } + public function testValueToLabelIfOptionNotFound(): void { $customField = new CustomField(); diff --git a/Tests/Unit/Entity/CustomItemTest.php b/Tests/Unit/Entity/CustomItemTest.php index 87215858e..8d5358402 100644 --- a/Tests/Unit/Entity/CustomItemTest.php +++ b/Tests/Unit/Entity/CustomItemTest.php @@ -15,7 +15,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefCustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomItemTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/Entity/CustomItemXrefCompanyTest.php b/Tests/Unit/Entity/CustomItemXrefCompanyTest.php index 4d035037e..86c789b32 100644 --- a/Tests/Unit/Entity/CustomItemXrefCompanyTest.php +++ b/Tests/Unit/Entity/CustomItemXrefCompanyTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Entity; -use DateTimeImmutable; use Mautic\LeadBundle\Entity\Company; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefCompany; @@ -15,7 +14,7 @@ public function testGetters(): void { $customItem = $this->createMock(CustomItem::class); $company = $this->createMock(Company::class); - $dateAdded = new DateTimeImmutable('2019-03-04 12:34:56'); + $dateAdded = new \DateTimeImmutable('2019-03-04 12:34:56'); $xref = new CustomItemXrefCompany( $customItem, $company, diff --git a/Tests/Unit/Entity/CustomItemXrefContactTest.php b/Tests/Unit/Entity/CustomItemXrefContactTest.php index 3f9c3e9de..483896a0f 100644 --- a/Tests/Unit/Entity/CustomItemXrefContactTest.php +++ b/Tests/Unit/Entity/CustomItemXrefContactTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Entity; -use DateTimeImmutable; use Mautic\LeadBundle\Entity\Lead; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefContact; @@ -15,7 +14,7 @@ public function testGetters(): void { $customItem = $this->createMock(CustomItem::class); $contact = $this->createMock(Lead::class); - $dateAdded = new DateTimeImmutable('2019-03-04 12:34:56'); + $dateAdded = new \DateTimeImmutable('2019-03-04 12:34:56'); $xref = new CustomItemXrefContact( $customItem, $contact, diff --git a/Tests/Unit/Entity/CustomItemXrefCustomItemTest.php b/Tests/Unit/Entity/CustomItemXrefCustomItemTest.php index 92140d119..b000bb451 100644 --- a/Tests/Unit/Entity/CustomItemXrefCustomItemTest.php +++ b/Tests/Unit/Entity/CustomItemXrefCustomItemTest.php @@ -4,10 +4,8 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Entity; -use DateTimeImmutable; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefCustomItem; -use UnexpectedValueException; class CustomItemXrefCustomItemTest extends \PHPUnit\Framework\TestCase { @@ -15,7 +13,7 @@ public function testGettersIfCustomItemAIsLower(): void { $customItemA = $this->createMock(CustomItem::class); $customItemB = $this->createMock(CustomItem::class); - $dateAdded = new DateTimeImmutable('2019-03-04 12:34:56'); + $dateAdded = new \DateTimeImmutable('2019-03-04 12:34:56'); $customItemA->method('getId')->willReturn(33); $customItemB->method('getId')->willReturn(55); @@ -37,7 +35,7 @@ public function testGettersIfCustomItemBIsLower(): void { $customItemA = $this->createMock(CustomItem::class); $customItemB = $this->createMock(CustomItem::class); - $dateAdded = new DateTimeImmutable('2019-03-04 12:34:56'); + $dateAdded = new \DateTimeImmutable('2019-03-04 12:34:56'); $customItemA->method('getId')->willReturn(55); $customItemB->method('getId')->willReturn(33); @@ -57,12 +55,12 @@ public function testGettersIfCustomItemsAreEqual(): void { $customItemA = $this->createMock(CustomItem::class); $customItemB = $this->createMock(CustomItem::class); - $dateAdded = new DateTimeImmutable('2019-03-04 12:34:56'); + $dateAdded = new \DateTimeImmutable('2019-03-04 12:34:56'); $customItemA->method('getId')->willReturn(55); $customItemB->method('getId')->willReturn(55); - $this->expectException(UnexpectedValueException::class); + $this->expectException(\UnexpectedValueException::class); new CustomItemXrefCustomItem( $customItemA, diff --git a/Tests/Unit/EventListener/ApiSubscriberTest.php b/Tests/Unit/EventListener/ApiSubscriberTest.php index 711d0179e..6674a23f7 100644 --- a/Tests/Unit/EventListener/ApiSubscriberTest.php +++ b/Tests/Unit/EventListener/ApiSubscriberTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\EventListener; -use InvalidArgumentException; use Mautic\ApiBundle\Event\ApiEntityEvent; use Mautic\LeadBundle\Entity\Lead; use Mautic\LeadBundle\Provider\FilterOperatorProviderInterface; @@ -21,10 +20,18 @@ use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ApiSubscriberTest extends \PHPUnit\Framework\TestCase { + private const CONTROLLER_METHODS = [ + 'newEntityAction', + 'newEntitiesAction', + 'editEntityAction', + 'editEntitiesAction', + ]; + private const CONTROLLER_CLASS = 'Mautic\LeadBundle\Controller\Api\LeadApiController'; + private $configProvider; private $customObjectModel; @@ -48,7 +55,7 @@ protected function setUp(): void $this->customObjectModel = $this->createMock(CustomObjectModel::class); $this->customItemModel = $this->createMock(CustomItemModel::class); $this->apiEntityEvent = $this->createMock(ApiEntityEvent::class); - $this->request = $this->createMock(Request::class); + $this->request = new Request(); $this->apiSubscriber = new ApiSubscriber( $this->configProvider, $this->customObjectModel, @@ -74,7 +81,23 @@ public function testPluginDisabled(): void $this->apiSubscriber->validateCustomObjectsInContactRequest($this->apiEntityEvent); } - public function testGetCustomObjectsFromContactCreateRequestForUnsupportedApiEndpoint(): void + /** + * @return iterable + */ + public function dataGetCustomObjectsFromContactCreateRequestForUnsupportedApiEndpoint(): iterable + { + foreach (self::CONTROLLER_METHODS as $method) { + yield ['Mautic\UnknownBundle\Controller\Api\UnknownController::'.$method]; + } + + yield [self::CONTROLLER_CLASS.'::unknownAction']; + yield [self::CONTROLLER_CLASS.'::unknownMethod']; + } + + /** + * @dataProvider dataGetCustomObjectsFromContactCreateRequestForUnsupportedApiEndpoint + */ + public function testGetCustomObjectsFromContactCreateRequestForUnsupportedApiEndpoint(string $controller): void { $this->configProvider->expects($this->once()) ->method('pluginIsEnabled') @@ -82,9 +105,19 @@ public function testGetCustomObjectsFromContactCreateRequestForUnsupportedApiEnd $this->apiEntityEvent->expects($this->once()) ->method('getEntityRequestParameters') - ->willReturn([]); + ->willReturn([ + 'email' => 'john@doe.email', + 'customObjects' => [ + 'data' => [ + [ + 'alias' => 'object-1-alias', + 'data' => [[]], + ], + ], + ], + ]); - $this->request->method('getPathInfo')->willReturn('/api/unicorn'); + $this->setControllerToRequest($controller); $this->apiEntityEvent->expects($this->never()) ->method('getEntity'); @@ -98,7 +131,7 @@ public function testGetCustomObjectsFromContactCreateRequestWithoutCustomObjects ->method('pluginIsEnabled') ->willReturn(true); - $this->request->method('getPathInfo')->willReturn('/api/contacts/new'); + $this->setControllerToRequest(); $this->apiEntityEvent->expects($this->once()) ->method('getEntityRequestParameters') @@ -110,13 +143,26 @@ public function testGetCustomObjectsFromContactCreateRequestWithoutCustomObjects $this->apiSubscriber->validateCustomObjectsInContactRequest($this->apiEntityEvent); } - public function testValidateCustomObjectsInContactRequestWhenCustomObjectNotFoundByAlias(): void + /** + * @return iterable + */ + public function dataValidateCustomObjectsInContactRequestWhenCustomObjectNotFoundByAlias(): iterable + { + foreach (self::CONTROLLER_METHODS as $method) { + yield [self::CONTROLLER_CLASS.'::'.$method]; + } + } + + /** + * @dataProvider dataValidateCustomObjectsInContactRequestWhenCustomObjectNotFoundByAlias + */ + public function testValidateCustomObjectsInContactRequestWhenCustomObjectNotFoundByAlias(string $controller): void { $this->configProvider->expects($this->once()) ->method('pluginIsEnabled') ->willReturn(true); - $this->request->method('getPathInfo')->willReturn('/api/contacts/new'); + $this->setControllerToRequest($controller); $this->apiEntityEvent->expects($this->once()) ->method('getEntityRequestParameters') @@ -152,7 +198,7 @@ public function testValidateCustomObjectsInContactRequestWhenCustomObjectNotFoun ->method('pluginIsEnabled') ->willReturn(true); - $this->request->method('getPathInfo')->willReturn('/api/contacts/new'); + $this->setControllerToRequest(); $this->apiEntityEvent->expects($this->once()) ->method('getEntityRequestParameters') @@ -188,7 +234,7 @@ public function testValidateCustomObjectsInContactRequestWhenCustomObjectDoesNot ->method('pluginIsEnabled') ->willReturn(true); - $this->request->method('getPathInfo')->willReturn('/api/contacts/new'); + $this->setControllerToRequest(); $this->apiEntityEvent->expects($this->once()) ->method('getEntityRequestParameters') @@ -207,7 +253,7 @@ public function testValidateCustomObjectsInContactRequestWhenCustomObjectDoesNot ->method('getEntity') ->willReturn(new Lead()); - $this->expectException(InvalidArgumentException::class); + $this->expectException(\InvalidArgumentException::class); $this->expectExceptionCode(Response::HTTP_BAD_REQUEST); $this->apiSubscriber->validateCustomObjectsInContactRequest($this->apiEntityEvent); } @@ -218,7 +264,7 @@ public function testValidateCustomObjectsInContactRequestWhenCustomItemNotFound( ->method('pluginIsEnabled') ->willReturn(true); - $this->request->method('getPathInfo')->willReturn('/api/contacts/new'); + $this->setControllerToRequest(); $this->apiEntityEvent->expects($this->once()) ->method('getEntityRequestParameters') @@ -261,7 +307,7 @@ public function testValidateCustomObjectsInContactRequestForCustomItemEdit(): vo ->method('pluginIsEnabled') ->willReturn(true); - $this->request->method('getPathInfo')->willReturn('/api/contacts/new'); + $this->setControllerToRequest(); $this->apiEntityEvent->expects($this->once()) ->method('getEntityRequestParameters') @@ -342,7 +388,7 @@ public function testSaveCustomObjectsInContactRequestForNewCustomItem(): void ->method('pluginIsEnabled') ->willReturn(true); - $this->request->method('getPathInfo')->willReturn('/api/contacts/new'); + $this->setControllerToRequest(); $this->apiEntityEvent->expects($this->once()) ->method('getEntityRequestParameters') @@ -408,7 +454,7 @@ public function testSaveCustomObjectsInContactRequestForNewCustomItem(): void ->method('save') ->with($this->callback(function (CustomItem $customItem) { $this->assertSame('Test Item', $customItem->getName()); - $skuValue = $customItem->findCustomFieldValueForFieldAlias('sku'); + $skuValue = $customItem->findCustomFieldValueForFieldAlias('sku'); $priceValue = $customItem->findCustomFieldValueForFieldAlias('price'); $this->assertSame('d2345f', $skuValue->getValue()); $this->assertSame(237, $priceValue->getValue()); @@ -418,4 +464,9 @@ public function testSaveCustomObjectsInContactRequestForNewCustomItem(): void $this->apiSubscriber->saveCustomObjectsInContactRequest($this->apiEntityEvent); } + + private function setControllerToRequest(string $controller = self::CONTROLLER_CLASS.'::'.self::CONTROLLER_METHODS[0]): void + { + $this->request->attributes->set('_controller', $controller); + } } diff --git a/Tests/Unit/EventListener/AssetsSubscriberTest.php b/Tests/Unit/EventListener/AssetsSubscriberTest.php index ec20fc3c9..f76d4cf60 100644 --- a/Tests/Unit/EventListener/AssetsSubscriberTest.php +++ b/Tests/Unit/EventListener/AssetsSubscriberTest.php @@ -4,19 +4,24 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\EventListener; -use Mautic\CoreBundle\Templating\Helper\AssetsHelper; +use Mautic\CoreBundle\Helper\CoreParametersHelper; +use Mautic\CoreBundle\Twig\Helper\AssetsHelper; use MauticPlugin\CustomObjectsBundle\EventListener\AssetsSubscriber; use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; +use Symfony\Component\Asset\Packages; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; class AssetsSubscriberTest extends \PHPUnit\Framework\TestCase { + private $packages; + + private $coreParametersHelper; private $assetsHelper; private $configProvider; - private $getResponseEvent; + private $requestEvent; private $request; @@ -26,11 +31,16 @@ protected function setUp(): void { parent::setUp(); - $this->assetsHelper = $this->createMock(AssetsHelper::class); - $this->configProvider = $this->createMock(ConfigProvider::class); - $this->getResponseEvent = $this->createMock(GetResponseEvent::class); - $this->request = $this->createMock(Request::class); - $this->assetsSubscriber = new AssetsSubscriber($this->assetsHelper, $this->configProvider); + $this->packages = $this->createMock(Packages::class); + $this->coreParametersHelper = $this->createMock(CoreParametersHelper::class); + $this->assetsHelper = new AssetsHelper( + $this->packages, + $this->coreParametersHelper + ); + $this->configProvider = $this->createMock(ConfigProvider::class); + $this->requestEvent = $this->createMock(RequestEvent::class); + $this->request = $this->createMock(Request::class); + $this->assetsSubscriber = new AssetsSubscriber($this->assetsHelper, $this->configProvider); } public function testPluginDisabled(): void @@ -39,13 +49,10 @@ public function testPluginDisabled(): void ->method('pluginIsEnabled') ->willReturn(false); - $this->getResponseEvent->expects($this->never()) - ->method('isMasterRequest'); - - $this->assetsHelper->expects($this->never()) - ->method('addStylesheet'); + $this->requestEvent->expects($this->never()) + ->method('isMainRequest'); - $this->assetsSubscriber->loadAssets($this->getResponseEvent); + $this->assetsSubscriber->loadAssets($this->requestEvent); } public function testPluginEnabledOnPublicPage(): void @@ -54,11 +61,11 @@ public function testPluginEnabledOnPublicPage(): void ->method('pluginIsEnabled') ->willReturn(true); - $this->getResponseEvent->expects($this->once()) - ->method('isMasterRequest') + $this->requestEvent->expects($this->once()) + ->method('isMainRequest') ->willReturn(true); - $this->getResponseEvent->expects($this->once()) + $this->requestEvent->expects($this->once()) ->method('getRequest') ->willReturn($this->request); @@ -66,10 +73,7 @@ public function testPluginEnabledOnPublicPage(): void ->method('getPathInfo') ->willReturn('/email/unsubscribe/5c9f4105548a6783784018'); - $this->assetsHelper->expects($this->never()) - ->method('addStylesheet'); - - $this->assetsSubscriber->loadAssets($this->getResponseEvent); + $this->assetsSubscriber->loadAssets($this->requestEvent); } public function testPluginEnabled(): void @@ -78,11 +82,11 @@ public function testPluginEnabled(): void ->method('pluginIsEnabled') ->willReturn(true); - $this->getResponseEvent->expects($this->once()) - ->method('isMasterRequest') + $this->requestEvent->expects($this->once()) + ->method('isMainRequest') ->willReturn(true); - $this->getResponseEvent->expects($this->once()) + $this->requestEvent->expects($this->once()) ->method('getRequest') ->willReturn($this->request); @@ -90,9 +94,6 @@ public function testPluginEnabled(): void ->method('getPathInfo') ->willReturn('/s/dashboard'); - $this->assetsHelper->expects($this->once()) - ->method('addStylesheet'); - - $this->assetsSubscriber->loadAssets($this->getResponseEvent); + $this->assetsSubscriber->loadAssets($this->requestEvent); } } diff --git a/Tests/Unit/EventListener/CampaignSubscriberTest.php b/Tests/Unit/EventListener/CampaignSubscriberTest.php index 5f9c65ee1..c609fe7c8 100644 --- a/Tests/Unit/EventListener/CampaignSubscriberTest.php +++ b/Tests/Unit/EventListener/CampaignSubscriberTest.php @@ -7,6 +7,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\QueryBuilder; +use Doctrine\DBAL\Result; use Doctrine\DBAL\Statement; use Mautic\CampaignBundle\Event\CampaignBuilderEvent; use Mautic\CampaignBundle\Event\CampaignExecutionEvent; @@ -26,7 +27,7 @@ use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; use MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\QueryFilterFactory; use PHPUnit\Framework\TestCase; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CampaignSubscriberTest extends TestCase { @@ -52,6 +53,7 @@ class CampaignSubscriberTest extends TestCase private $queryBuilder; private $segmentQueryBuilder; private $statement; + private $result; /** * @var CampaignSubscriber @@ -61,9 +63,6 @@ class CampaignSubscriberTest extends TestCase protected function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); - - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); $this->customFieldModel = $this->createMock(CustomFieldModel::class); $this->customObjectModel = $this->createMock(CustomObjectModel::class); @@ -81,6 +80,7 @@ protected function setUp(): void $this->queryBuilder = $this->createMock(QueryBuilder::class); $this->segmentQueryBuilder = $this->createMock(SegmentQueryBuilder::class); $this->statement = $this->createMock(Statement::class); + $this->result = $this->createMock(Result::class); $this->campaignSubscriber = new CampaignSubscriber( $this->customFieldModel, $this->customObjectModel, @@ -380,7 +380,7 @@ public function testOnCampaignTriggerConditionWhenItemNotFound(): void $this->queryBuilder->expects($this->once()) ->method('execute') - ->willReturn($this->statement); + ->willReturn($this->result); $this->queryFilterFactory->expects($this->once()) ->method('configureQueryBuilderFromSegmentFilter') @@ -413,8 +413,8 @@ public function testOnCampaignTriggerConditionWhenItemNotFound(): void ->method('fetchEntity') ->willReturn($this->customField); - $this->statement->expects($this->once()) - ->method('fetchColumn') + $this->result->expects($this->once()) + ->method('fetchOne') ->willReturn(false); $this->campaignExecutionEvent->expects($this->once()) @@ -436,7 +436,7 @@ public function testOnCampaignTriggerCondition(): void $this->queryBuilder->expects($this->once()) ->method('execute') - ->willReturn($this->statement); + ->willReturn($this->result); $this->queryFilterFactory->expects($this->once()) ->method('configureQueryBuilderFromSegmentFilter') @@ -473,8 +473,8 @@ public function testOnCampaignTriggerCondition(): void ->method('setChannel') ->with('customItem', 4344); - $this->statement->expects($this->once()) - ->method('fetchColumn') + $this->result->expects($this->once()) + ->method('fetchOne') ->willReturn('4344'); $this->campaignExecutionEvent->expects($this->once()) diff --git a/Tests/Unit/EventListener/ContactSubscriberTest.php b/Tests/Unit/EventListener/ContactSubscriberTest.php index 80718dbb6..ed935dd7a 100644 --- a/Tests/Unit/EventListener/ContactSubscriberTest.php +++ b/Tests/Unit/EventListener/ContactSubscriberTest.php @@ -16,7 +16,9 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; -use Symfony\Component\Translation\TranslatorInterface; +use MauticPlugin\CustomObjectsBundle\Repository\CustomItemXrefContactRepository; +use PHPUnit\Framework\MockObject\MockObject; +use Symfony\Contracts\Translation\TranslatorInterface; class ContactSubscriberTest extends \PHPUnit\Framework\TestCase { @@ -28,6 +30,11 @@ class ContactSubscriberTest extends \PHPUnit\Framework\TestCase private $leadTimelineEvent; private $leadEventLogRepo; + /** + * @var MockObject&CustomItemXrefContactRepository + */ + private MockObject $ciXcontactRepo; + /** * @var ContactSubscriber */ @@ -44,12 +51,14 @@ protected function setUp(): void $this->configProvider = $this->createMock(ConfigProvider::class); $this->leadTimelineEvent = $this->createMock(LeadTimelineEvent::class); $this->leadEventLogRepo = $this->createMock(LeadEventLogRepository::class); + $this->ciXcontactRepo = $this->createMock(CustomItemXrefContactRepository::class); $this->subscriber = new ContactSubscriber( $this->entityManager, $this->translator, $this->routeProvider, $this->customItemModel, - $this->configProvider + $this->configProvider, + $this->ciXcontactRepo ); } @@ -176,7 +185,7 @@ public function testPluginEnabledOnPublicPageWhenItemFound(): void 'id' => 444, ], 'contactId' => 333, - 'contentTemplate' => 'CustomObjectsBundle:SubscribedEvents\Timeline:link.html.php', + 'contentTemplate' => '@CustomObjects/SubscribedEvents/Timeline/link.html.twig', ]); $this->subscriber->onTimelineGenerate($this->leadTimelineEvent); @@ -273,7 +282,7 @@ public function testPluginEnabledOnPublicPageWhenItemNotFound(): void 'id' => 444, ], 'contactId' => 333, - 'contentTemplate' => 'CustomObjectsBundle:SubscribedEvents\Timeline:link.html.php', + 'contentTemplate' => '@CustomObjects/SubscribedEvents/Timeline/link.html.twig', ]); $this->subscriber->onTimelineGenerate($this->leadTimelineEvent); diff --git a/Tests/Unit/EventListener/ContactTabSubscriberTest.php b/Tests/Unit/EventListener/ContactTabSubscriberTest.php index 62499bc83..30d945723 100644 --- a/Tests/Unit/EventListener/ContactTabSubscriberTest.php +++ b/Tests/Unit/EventListener/ContactTabSubscriberTest.php @@ -17,7 +17,7 @@ use MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ContactTabSubscriberTest extends TestCase { @@ -123,8 +123,8 @@ public function testForTabsContext(): void ->method('checkContext') ->willReturnMap( [ - ['MauticLeadBundle:Lead:lead.html.php', 'tabs', true], - ['MauticLeadBundle:Lead:lead.html.php', 'tabs.content', false], + ['@MauticLead/Lead/lead.html.twig', 'tabs', true], + ['@MauticLead/Lead/lead.html.twig', 'tabs.content', false], ] ); @@ -136,7 +136,7 @@ public function testForTabsContext(): void ->method('addTemplate') ->withConsecutive( [ - 'CustomObjectsBundle:SubscribedEvents/Tab:link.html.php', + '@CustomObjects/SubscribedEvents/Tab/link.html.twig', [ 'count' => 13, 'title' => 'Object A', @@ -144,7 +144,7 @@ public function testForTabsContext(): void ], ], [ - 'CustomObjectsBundle:SubscribedEvents/Tab:modal.html.php', + '@CustomObjects/SubscribedEvents/Tab/modal.html.twig', ] ); @@ -176,8 +176,8 @@ public function testForTabContentsContext(): void ->method('checkContext') ->willReturnMap( [ - ['MauticLeadBundle:Lead:lead.html.php', 'tabs', false], - ['MauticLeadBundle:Lead:lead.html.php', 'tabs.content', true], + ['@MauticLead/Lead/lead.html.twig', 'tabs', false], + ['@MauticLead/Lead/lead.html.twig', 'tabs.content', true], ] ); @@ -218,7 +218,7 @@ public function testForTabContentsContext(): void $this->customContentEvent->expects($this->once()) ->method('addTemplate') ->with( - 'CustomObjectsBundle:SubscribedEvents/Tab:content.html.php', + '@CustomObjects/SubscribedEvents/Tab/content.html.twig', [ 'customObjectId' => 555, 'currentEntityId' => 45, diff --git a/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php b/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php index e250adfcd..abdb79f33 100644 --- a/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php +++ b/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php @@ -12,7 +12,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\EventListener\CustomFieldPostLoadSubscriber; use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomFieldPostLoadSubscriberTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/EventListener/CustomItemButtonSubscriberTest.php b/Tests/Unit/EventListener/CustomItemButtonSubscriberTest.php index ed44bf1a0..093fed29d 100644 --- a/Tests/Unit/EventListener/CustomItemButtonSubscriberTest.php +++ b/Tests/Unit/EventListener/CustomItemButtonSubscriberTest.php @@ -15,7 +15,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomItemButtonSubscriberTest extends TestCase { diff --git a/Tests/Unit/EventListener/CustomItemPostSaveSubscriberTest.php b/Tests/Unit/EventListener/CustomItemPostSaveSubscriberTest.php index f28cc0113..b1a1e38ed 100644 --- a/Tests/Unit/EventListener/CustomItemPostSaveSubscriberTest.php +++ b/Tests/Unit/EventListener/CustomItemPostSaveSubscriberTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\EventListener; -use Exception; use MauticPlugin\CustomObjectsBundle\CustomItemEvents; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; @@ -33,7 +32,7 @@ public function __construct() public function fetchEntity(int $id): CustomItem { - throw new Exception('This should not have been called.'); + throw new \Exception('This should not have been called.'); } }; @@ -60,7 +59,7 @@ public function __construct() $subscriber->postSave($event); - // No actual assertions made, we're just ensuring an exception is not thrown. + // No actual assertions made, we're just ensuring an \Exception is not thrown. $this->addToAssertionCount(1); } @@ -74,7 +73,7 @@ public function __construct() public function fetchEntity(int $id): CustomItem { - throw new Exception('This should not have been called.'); + throw new \Exception('This should not have been called.'); } }; @@ -101,7 +100,7 @@ public function __construct() $subscriber->postSave($event); - // No actual assertions made, we're just ensuring an exception is not thrown. + // No actual assertions made, we're just ensuring an \Exception is not thrown. $this->addToAssertionCount(1); } } diff --git a/Tests/Unit/EventListener/CustomItemTabSubscriberTest.php b/Tests/Unit/EventListener/CustomItemTabSubscriberTest.php index 2e4e7bb5e..fea8001e9 100644 --- a/Tests/Unit/EventListener/CustomItemTabSubscriberTest.php +++ b/Tests/Unit/EventListener/CustomItemTabSubscriberTest.php @@ -15,7 +15,7 @@ use MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomItemTabSubscriberTest extends TestCase { @@ -105,8 +105,8 @@ public function testForTabsContext(): void $this->customContentEvent ->method('checkContext') ->withConsecutive( - ['CustomObjectsBundle:CustomItem:detail.html.php', 'tabs'], - ['CustomObjectsBundle:CustomItem:detail.html.php', 'tabs.content'] + ['@CustomObjects/CustomItem/detail.html.twig', 'tabs'], + ['@CustomObjects/CustomItem/detail.html.twig', 'tabs.content'] ) ->willReturnOnConsecutiveCalls(true, false); @@ -118,7 +118,7 @@ public function testForTabsContext(): void ->method('addTemplate') ->withConsecutive( [ - 'CustomObjectsBundle:SubscribedEvents/Tab:link.html.php', + '@CustomObjects/SubscribedEvents/Tab/link.html.twig', [ 'count' => 13, 'title' => 'Object A', @@ -126,7 +126,7 @@ public function testForTabsContext(): void ], ], [ - 'CustomObjectsBundle:SubscribedEvents/Tab:modal.html.php', + '@CustomObjects/SubscribedEvents/Tab/modal.html.twig', ] ); @@ -158,8 +158,8 @@ public function testForTabsContextWhenTheCustomItemMatchesCustomObject(): void $this->customContentEvent ->method('checkContext') ->withConsecutive( - ['CustomObjectsBundle:CustomItem:detail.html.php', 'tabs'], - ['CustomObjectsBundle:CustomItem:detail.html.php', 'tabs.content'] + ['@CustomObjects/CustomItem/detail.html.twig', 'tabs'], + ['@CustomObjects/CustomItem/detail.html.twig', 'tabs.content'] ) ->willReturn(true, false); @@ -169,7 +169,7 @@ public function testForTabsContextWhenTheCustomItemMatchesCustomObject(): void $this->customContentEvent->expects($this->once()) ->method('addTemplate') - ->with('CustomObjectsBundle:SubscribedEvents/Tab:modal.html.php'); + ->with('@CustomObjects/SubscribedEvents/Tab/modal.html.twig'); $this->customObjectModel->expects($this->once()) ->method('getMasterCustomObjects') @@ -194,8 +194,8 @@ public function testForTabContentsContext(): void $this->customContentEvent ->method('checkContext') ->withConsecutive( - ['CustomObjectsBundle:CustomItem:detail.html.php', 'tabs'], - ['CustomObjectsBundle:CustomItem:detail.html.php', 'tabs.content'] + ['@CustomObjects/CustomItem/detail.html.twig', 'tabs'], + ['@CustomObjects/CustomItem/detail.html.twig', 'tabs.content'] ) ->willReturn(false, true); @@ -236,7 +236,7 @@ public function testForTabContentsContext(): void $this->customContentEvent->expects($this->once()) ->method('addTemplate') ->with( - 'CustomObjectsBundle:SubscribedEvents/Tab:content.html.php', + '@CustomObjects/SubscribedEvents/Tab/content.html.twig', [ 'customObjectId' => 555, 'currentEntityId' => 45, diff --git a/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php b/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php index 585817fbb..ec7bf22d0 100644 --- a/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php +++ b/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php @@ -72,8 +72,6 @@ protected function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); - $this->entityManager = $this->createMock(EntityManager::class); $this->queryBuilder = $this->createMock(QueryBuilder::class); $this->queryBuilderDbal = $this->createMock(DbalQueryBuilder::class); diff --git a/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php b/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php index 3f1b0738f..83b3fce2d 100644 --- a/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php +++ b/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php @@ -12,7 +12,7 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectPermissionProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectRouteProvider; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomObjectButtonSubscriberTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/EventListener/CustomObjectPostSaveSubscriberTest.php b/Tests/Unit/EventListener/CustomObjectPostSaveSubscriberTest.php index 5fb8f36fe..5422c7ea3 100644 --- a/Tests/Unit/EventListener/CustomObjectPostSaveSubscriberTest.php +++ b/Tests/Unit/EventListener/CustomObjectPostSaveSubscriberTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\EventListener; -use Exception; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Event\CustomObjectEvent; use MauticPlugin\CustomObjectsBundle\EventListener\CustomObjectPostSaveSubscriber; @@ -53,7 +52,7 @@ public function __construct() public function saveEntity($entity, $unlock = true): void { - throw new Exception('Should not have been called.'); + throw new \Exception('Should not have been called.'); } }; @@ -65,7 +64,7 @@ public function saveEntity($entity, $unlock = true): void $subscriber->postSave($event); - // Asserting that the exception is not thrown + // Asserting that the \Exception is not thrown $this->addToAssertionCount(1); } } diff --git a/Tests/Unit/EventListener/DynamicContentSubscriberTest.php b/Tests/Unit/EventListener/DynamicContentSubscriberTest.php index 147c95aab..5bfaf35e6 100644 --- a/Tests/Unit/EventListener/DynamicContentSubscriberTest.php +++ b/Tests/Unit/EventListener/DynamicContentSubscriberTest.php @@ -4,149 +4,176 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\EventListener; -use Doctrine\DBAL\Statement; +use Mautic\DynamicContentBundle\DynamicContentEvents; use Mautic\DynamicContentBundle\Event\ContactFiltersEvaluateEvent; use Mautic\LeadBundle\Entity\Lead; -use Mautic\LeadBundle\Segment\Query\QueryBuilder; use MauticPlugin\CustomObjectsBundle\EventListener\DynamicContentSubscriber; use MauticPlugin\CustomObjectsBundle\Exception\InvalidSegmentFilterException; -use MauticPlugin\CustomObjectsBundle\Helper\QueryFilterHelper; +use MauticPlugin\CustomObjectsBundle\Helper\ContactFilterMatcher; use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; use MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\CustomFieldFilterQueryBuilder; use MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\CustomItemNameFilterQueryBuilder; use MauticPlugin\CustomObjectsBundle\Segment\Query\Filter\QueryFilterFactory; -use Monolog\Logger; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; class DynamicContentSubscriberTest extends TestCase { - /** @var ConfigProvider|MockObject */ - private $configProviderMock; + /** @var QueryFilterFactory&MockObject */ + private MockObject $queryFilterFactory; - /** @var QueryFilterHelper|MockObject */ - private $queryFilterHelperMock; + /** @var ContactFilterMatcher&MockObject */ + private MockObject $contactFilterMatcher; - /** @var QueryFilterFactory|MockObject */ - private $queryFilterFactory; + /** @var ConfigProvider&MockObject */ + private MockObject $configProvider; - /** @var Logger|MockObject */ - private $loggerMock; - - /** @var QueryBuilder|MockObject */ - private $queryBuilderMock; - - /** @var DynamicContentSubscriber */ - private $dynamicContentSubscriber; - - /** @var Statement|MockObject */ - private $statementMock; + private DynamicContentSubscriber $subscriber; protected function setUp(): void { parent::setUp(); - $this->configProviderMock = $this->createMock(ConfigProvider::class); - $this->queryFilterFactory = $this->createMock(QueryFilterFactory::class); - $this->queryFilterHelperMock = $this->createMock(QueryFilterHelper::class); - $this->loggerMock = $this->createMock(Logger::class); - $this->queryBuilderMock = $this->createMock(QueryBuilder::class); - $this->statementMock = $this->createMock(Statement::class); + $this->queryFilterFactory = $this->createMock(QueryFilterFactory::class); + $this->contactFilterMatcher = $this->createMock(ContactFilterMatcher::class); + $this->configProvider = $this->createMock(ConfigProvider::class); - $this->dynamicContentSubscriber = new DynamicContentSubscriber( + $this->subscriber = new DynamicContentSubscriber( $this->queryFilterFactory, - $this->queryFilterHelperMock, - $this->configProviderMock, - $this->loggerMock + $this->contactFilterMatcher, + $this->configProvider, ); } - public function testOnCampaignBuildWhenPluginDisabled(): void + public function testGetSubscribedEventsReturnsCorrectMapping(): void + { + $events = DynamicContentSubscriber::getSubscribedEvents(); + + $this->assertArrayHasKey(DynamicContentEvents::ON_CONTACTS_FILTER_EVALUATE, $events); + $this->assertSame(['evaluateFilters', 0], $events[DynamicContentEvents::ON_CONTACTS_FILTER_EVALUATE]); + } + + public function testEvaluateFiltersSkipsWhenEventAlreadyEvaluated(): void { - $this->configProviderMock->expects($this->once()) + $event = $this->buildEvent(); + $event->setIsEvaluated(true); + + // pluginIsEnabled must never be called — early exit on isEvaluated() + $this->configProvider->expects($this->never())->method('pluginIsEnabled'); + $this->queryFilterFactory->expects($this->never())->method('configureQueryBuilderFromSegmentFilter'); + $this->contactFilterMatcher->expects($this->never())->method('match'); + + $this->subscriber->evaluateFilters($event); + } + + public function testEvaluateFiltersSkipsWhenPluginDisabled(): void + { + $this->configProvider->expects($this->once()) ->method('pluginIsEnabled') ->willReturn(false); $this->queryFilterFactory->expects($this->never())->method('configureQueryBuilderFromSegmentFilter'); + $this->contactFilterMatcher->expects($this->never())->method('match'); - $this->dynamicContentSubscriber->evaluateFilters($this->buildEventWithFilters()); + $this->subscriber->evaluateFilters($this->buildEvent()); } - public function testFiltersNotEvaluatedIfEventMarkedEvaluated(): void + public function testEvaluateFiltersSkipsWhenNoCustomObjectFiltersFound(): void { - $this->configProviderMock->expects($this->once())->method('pluginIsEnabled')->willReturn(true); + $this->configProvider->expects($this->once()) + ->method('pluginIsEnabled') + ->willReturn(true); - $event = $this->buildEventWithFilters(); - $event->setIsEvaluated(true); + // All filters throw → no custom object filters present + $this->queryFilterFactory->expects($this->exactly(2)) + ->method('configureQueryBuilderFromSegmentFilter') + ->willThrowException(new InvalidSegmentFilterException('not a CO filter')); - $this->queryFilterFactory->expects($this->never())->method('configureQueryBuilderFromSegmentFilter'); + $this->contactFilterMatcher->expects($this->never())->method('match'); - $this->dynamicContentSubscriber->evaluateFilters($event); + $event = $this->buildEvent(); + $this->subscriber->evaluateFilters($event); + + $this->assertFalse($event->isEvaluated()); } - public function testFiltersInsertedIntoEvent(): void + public function testEvaluateFiltersMatchesAndSetsResultOnEvent(): void { - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); + $contact = new Lead(); + $contact->setFields(['email' => 'test@example.com']); + + $event = new ContactFiltersEvaluateEvent($this->buildFilters(), $contact); - $this->configProviderMock->expects($this->once())->method('pluginIsEnabled')->willReturn(true); + $this->configProvider->expects($this->once()) + ->method('pluginIsEnabled') + ->willReturn(true); + // First filter throws (not a CO filter), second succeeds → hasCustomObjectFilters returns true $this->queryFilterFactory->expects($this->exactly(2)) ->method('configureQueryBuilderFromSegmentFilter') - ->withConsecutive( - [ - [ - 'type' => CustomFieldFilterQueryBuilder::getServiceId(), - 'table' => 'custom_field_text', - 'field' => 'cfwq_1', - 'foreign_table' => 'custom_objects', - ], - 'filter_custom_field_1', - ], - [ - [ - 'type' => CustomItemNameFilterQueryBuilder::getServiceId(), - 'table' => 'custom_field_text', - 'field' => 'cowq_2', - 'foreign_table' => 'custom_objects', - ], - 'filter_custom_item_1', - ] - ) ->will($this->onConsecutiveCalls( - $this->queryBuilderMock, - $this->throwException(new InvalidSegmentFilterException('Testing invalid segment handling here.')) + $this->throwException(new InvalidSegmentFilterException('not a CO filter')), + $this->returnValue(null), )); - $event = $this->buildEventWithFilters(); - $event->setIsEvaluated(false); + $this->contactFilterMatcher->expects($this->once()) + ->method('match') + ->with($this->buildFilters(), ['id' => null, 'email' => 'test@example.com']) + ->willReturn(true); + + $this->subscriber->evaluateFilters($event); + + $this->assertTrue($event->isEvaluated()); + $this->assertTrue($event->isMatched()); + } + + public function testEvaluateFiltersSetsMismatchOnEvent(): void + { + $contact = new Lead(); + $contact->setFields([]); + + $event = new ContactFiltersEvaluateEvent($this->buildFilters(), $contact); - $this->queryBuilderMock->expects($this->once())->method('execute')->willReturn($this->statementMock); + $this->configProvider->method('pluginIsEnabled')->willReturn(true); - $this->loggerMock - ->expects($this->never()) - ->method('addError'); + // First filter is a valid CO filter → hasCustomObjectFilters returns true immediately + $this->queryFilterFactory->expects($this->once()) + ->method('configureQueryBuilderFromSegmentFilter') + ->willReturn(null); + + $this->contactFilterMatcher->expects($this->once()) + ->method('match') + ->willReturn(false); - $this->dynamicContentSubscriber->evaluateFilters($event); + $this->subscriber->evaluateFilters($event); + + $this->assertTrue($event->isEvaluated()); + $this->assertFalse($event->isMatched()); } - private function buildEventWithFilters(): ContactFiltersEvaluateEvent + /** + * @return mixed[] + */ + private function buildFilters(): array { - return new ContactFiltersEvaluateEvent( - [ - 'custom_field_1' => [ - 'type' => CustomFieldFilterQueryBuilder::getServiceId(), - 'table' => 'custom_field_text', - 'field' => 'cfwq_1', - 'foreign_table' => 'custom_objects', - ], - 'custom_item_1' => [ - 'type' => CustomItemNameFilterQueryBuilder::getServiceId(), - 'table' => 'custom_field_text', - 'field' => 'cowq_2', - 'foreign_table' => 'custom_objects', - ], + return [ + 'custom_field_1' => [ + 'type' => CustomFieldFilterQueryBuilder::getServiceId(), + 'table' => 'custom_field_text', + 'field' => 'cfwq_1', + 'foreign_table' => 'custom_objects', ], - new Lead() - ); + 'custom_item_1' => [ + 'type' => CustomItemNameFilterQueryBuilder::getServiceId(), + 'table' => 'custom_field_text', + 'field' => 'cowq_2', + 'foreign_table' => 'custom_objects', + ], + ]; + } + + private function buildEvent(): ContactFiltersEvaluateEvent + { + return new ContactFiltersEvaluateEvent($this->buildFilters(), new Lead()); } } diff --git a/Tests/Unit/EventListener/FilterOperatorSubscriberTest.php b/Tests/Unit/EventListener/FilterOperatorSubscriberTest.php index 3afb8ca20..7be7eaf23 100644 --- a/Tests/Unit/EventListener/FilterOperatorSubscriberTest.php +++ b/Tests/Unit/EventListener/FilterOperatorSubscriberTest.php @@ -13,7 +13,7 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; final class FilterOperatorSubscriberTest extends \PHPUnit\Framework\TestCase { @@ -29,7 +29,6 @@ final class FilterOperatorSubscriberTest extends \PHPUnit\Framework\TestCase protected function setUp(): void { - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', getenv('MAUTIC_DB_PREFIX') ?: ''); $this->customObjectModelMock = $this->createMock(CustomObjectModel::class); $this->filterOperatorSubscriber = new FilterOperatorSubscriber($this->customObjectModelMock); } diff --git a/Tests/Unit/EventListener/ImportSubscriberTest.php b/Tests/Unit/EventListener/ImportSubscriberTest.php index 9f50f200a..664c97541 100644 --- a/Tests/Unit/EventListener/ImportSubscriberTest.php +++ b/Tests/Unit/EventListener/ImportSubscriberTest.php @@ -21,7 +21,7 @@ use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use MauticPlugin\CustomObjectsBundle\Repository\CustomFieldRepository; use Symfony\Component\Form\Form; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ImportSubscriberTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/EventListener/MenuSubscriberTest.php b/Tests/Unit/EventListener/MenuSubscriberTest.php index fd2566aba..39e46569c 100644 --- a/Tests/Unit/EventListener/MenuSubscriberTest.php +++ b/Tests/Unit/EventListener/MenuSubscriberTest.php @@ -10,7 +10,6 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel; use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; -use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectRouteProvider; use PHPUnit\Framework\TestCase; class MenuSubscriberTest extends TestCase @@ -155,18 +154,7 @@ public function testAdminMenu(): void ->method('fetchAllPublishedEntities'); $this->menuEvent->expects($this->once()) - ->method('addMenuItems') - ->willReturn([ - 'priority' => 61, - 'items' => [ - 'custom.object.config.menu.title' => [ - 'id' => CustomObjectRouteProvider::ROUTE_LIST, - 'route' => CustomObjectRouteProvider::ROUTE_LIST, - 'access' => 'custom_objects:custom_objects:view', - 'iconClass' => 'fa-list-alt', - ], - ], - ]); + ->method('addMenuItems'); $this->menuSubscriber->onBuildMenu($this->menuEvent); } diff --git a/Tests/Unit/EventListener/ReportSubscriberTest.php b/Tests/Unit/EventListener/ReportSubscriberTest.php index 5dc053f93..ae8a2742f 100644 --- a/Tests/Unit/EventListener/ReportSubscriberTest.php +++ b/Tests/Unit/EventListener/ReportSubscriberTest.php @@ -25,7 +25,8 @@ use MauticPlugin\CustomObjectsBundle\Repository\CustomObjectRepository; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ReportSubscriberTest extends TestCase { @@ -84,6 +85,11 @@ class ReportSubscriberTest extends TestCase */ private $connection; + /** + * @var MockObject|EventDispatcherInterface + */ + private $dispatcher; + /** * @var ReportHelper */ @@ -91,12 +97,11 @@ class ReportSubscriberTest extends TestCase protected function setUp(): void { - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', getenv('MAUTIC_DB_PREFIX') ?: ''); - $this->customObjectRepository = $this->createMock(CustomObjectRepository::class); $this->fieldsBuilder = $this->createMock(FieldsBuilder::class); $this->companyReportData = $this->createMock(CompanyReportData::class); - $this->reportHelper = new ReportHelper(); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->reportHelper = new ReportHelper($this->dispatcher); $this->translatorInterface = $this->createMock(TranslatorInterface::class); $this->reportSubscriber = new ReportSubscriber($this->customObjectRepository, $this->fieldsBuilder, $this->companyReportData, $this->reportHelper, $this->translatorInterface); $this->reportBuilderEvent = $this->createMock(ReportBuilderEvent::class); diff --git a/Tests/Unit/EventListener/SegmentFiltersChoicesGenerateSubscriberTest.php b/Tests/Unit/EventListener/SegmentFiltersChoicesGenerateSubscriberTest.php index 7f38fc534..cb5d41985 100644 --- a/Tests/Unit/EventListener/SegmentFiltersChoicesGenerateSubscriberTest.php +++ b/Tests/Unit/EventListener/SegmentFiltersChoicesGenerateSubscriberTest.php @@ -7,8 +7,14 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Criteria; use Mautic\LeadBundle\Event\LeadListFiltersChoicesEvent; +use Mautic\LeadBundle\Event\OverrideOperatorLabelEvent; +use Mautic\LeadBundle\Event\TypeOperatorsEvent; use Mautic\LeadBundle\LeadEvents; use Mautic\LeadBundle\Provider\FilterOperatorProviderInterface; +use Mautic\LeadBundle\Provider\TypeOperatorProvider; +use Mautic\LeadBundle\Provider\TypeOperatorProviderInterface; +use Mautic\LeadBundle\Segment\OperatorOptions; +use MauticPlugin\CustomObjectsBundle\CustomFieldType\DateType; use MauticPlugin\CustomObjectsBundle\CustomFieldType\IntType; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; @@ -16,12 +22,16 @@ use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider; use MauticPlugin\CustomObjectsBundle\Repository\CustomObjectRepository; +use MauticPlugin\CustomObjectsBundle\Tests\ProjectVersionTrait; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class SegmentFiltersChoicesGenerateSubscriberTest extends TestCase { + use ProjectVersionTrait; + /** * @var CustomObjectRepository|MockObject */ @@ -52,6 +62,16 @@ class SegmentFiltersChoicesGenerateSubscriberTest extends TestCase */ private $filterOperatorProvider; + /** + * @var TypeOperatorProviderInterface|MockObject + */ + private $typeOperatorProvider; + + /** + * @var EventDispatcherInterface|MockObject + */ + private $dispatcher; + public function setUp(): void { parent::setUp(); @@ -61,17 +81,27 @@ public function setUp(): void $this->configProvider = $this->createMock(ConfigProvider::class); $this->fieldTypeProvider = $this->createMock(CustomFieldTypeProvider::class); $this->filterOperatorProvider = $this->createMock(FilterOperatorProviderInterface::class); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->typeOperatorProvider = new TypeOperatorProvider( + $this->dispatcher, + $this->filterOperatorProvider + ); $this->subscriber = new SegmentFiltersChoicesGenerateSubscriber( $this->customObjectRepository, $this->translator, $this->configProvider, - $this->fieldTypeProvider + $this->fieldTypeProvider, + $this->typeOperatorProvider ); } public function testOnGenerateSegmentFilters(): void { + if (!$this->isCloudProject()) { + $this->markTestSkipped('Undefined index: default on TypeOperatorProvider.php:61 in 4.4'); + } + $customObject = new CustomObject(); $customObject->setId(1); $customObject->setNameSingular('Product'); @@ -98,116 +128,119 @@ public function testOnGenerateSegmentFilters(): void $allOperators = [ '=' => [ - 'label' => 'equals', - 'expr' => 'eq', - 'negate_expr' => 'neq', - ], + 'label' => 'equals', + 'expr' => 'eq', + 'negate_expr' => 'neq', + ], '!=' => [ - 'label' => 'not equal', - 'expr' => 'neq', - 'negate_expr' => 'eq', - ], + 'label' => 'not equal', + 'expr' => 'neq', + 'negate_expr' => 'eq', + ], 'gt' => [ - 'label' => 'greater than', - 'expr' => 'gt', - 'negate_expr' => 'lt', - ], + 'label' => 'greater than', + 'expr' => 'gt', + 'negate_expr' => 'lt', + ], 'gte' => [ - 'label' => 'greater than or equal', - 'expr' => 'gte', - 'negate_expr' => 'lt', - ], + 'label' => 'greater than or equal', + 'expr' => 'gte', + 'negate_expr' => 'lt', + ], 'lt' => [ - 'label' => 'less than', - 'expr' => 'lt', - 'negate_expr' => 'gt', - ], + 'label' => 'less than', + 'expr' => 'lt', + 'negate_expr' => 'gt', + ], 'lte' => [ - 'label' => 'less than or equal', - 'expr' => 'lte', - 'negate_expr' => 'gt', - ], + 'label' => 'less than or equal', + 'expr' => 'lte', + 'negate_expr' => 'gt', + ], 'empty' => [ - 'label' => 'empty', - 'expr' => 'empty', - 'negate_expr' => 'notEmpty', - ], + 'label' => 'empty', + 'expr' => 'empty', + 'negate_expr' => 'notEmpty', + ], '!empty' => [ - 'label' => 'not empty', - 'expr' => 'notEmpty', - 'negate_expr' => 'empty', - ], + 'label' => 'not empty', + 'expr' => 'notEmpty', + 'negate_expr' => 'empty', + ], 'like' => [ - 'label' => 'like', - 'expr' => 'like', - 'negate_expr' => 'notLike', - ], + 'label' => 'like', + 'expr' => 'like', + 'negate_expr' => 'notLike', + ], '!like' => [ - 'label' => 'not like', - 'expr' => 'notLike', - 'negate_expr' => 'like', - ], + 'label' => 'not like', + 'expr' => 'notLike', + 'negate_expr' => 'like', + ], 'between' => [ - 'label' => 'between', - 'expr' => 'between', - 'negate_expr' => 'notBetween', - 'hide' => true, - ], + 'label' => 'between', + 'expr' => 'between', + 'negate_expr' => 'notBetween', + ], '!between' => [ - 'label' => 'not between', - 'expr' => 'notBetween', - 'negate_expr' => 'between', - 'hide' => true, - ], + 'label' => 'not between', + 'expr' => 'notBetween', + 'negate_expr' => 'between', + ], 'in' => [ - 'label' => 'including', - 'expr' => 'in', - 'negate_expr' => 'notIn', - ], + 'label' => 'including', + 'expr' => 'in', + 'negate_expr' => 'notIn', + ], '!in' => [ - 'label' => 'excluding', - 'expr' => 'notIn', - 'negate_expr' => 'in', - ], + 'label' => 'excluding', + 'expr' => 'notIn', + 'negate_expr' => 'in', + ], 'regexp' => [ - 'label' => 'regexp', - 'expr' => 'regexp', - 'negate_expr' => 'notRegexp', - ], + 'label' => 'regexp', + 'expr' => 'regexp', + 'negate_expr' => 'notRegexp', + ], '!regexp' => [ - 'label' => 'not regexp', - 'expr' => 'notRegexp', - 'negate_expr' => 'regexp', - ], + 'label' => 'not regexp', + 'expr' => 'notRegexp', + 'negate_expr' => 'regexp', + ], 'date' => [ - 'label' => 'date', - 'expr' => 'date', - 'negate_expr' => 'date', - 'hide' => true, - ], + 'label' => 'date', + 'expr' => 'date', + 'negate_expr' => 'date', + 'hide' => true, + ], 'startsWith' => [ - 'label' => 'starts with', - 'expr' => 'startsWith', - 'negate_expr' => 'startsWith', - ], + 'label' => 'starts with', + 'expr' => 'startsWith', + 'negate_expr' => 'startsWith', + ], 'endsWith' => [ - 'label' => 'ends with', - 'expr' => 'endsWith', - 'negate_expr' => 'endsWith', - ], + 'label' => 'ends with', + 'expr' => 'endsWith', + 'negate_expr' => 'endsWith', + ], 'contains' => [ - 'label' => 'contains', - 'expr' => 'contains', - 'negate_expr' => 'contains', - ], + 'label' => 'contains', + 'expr' => 'contains', + 'negate_expr' => 'contains', + ], 'withinCustomObjects' => [ - 'label' => 'within custom objects', - 'expr' => 'withinCustomObjects', - 'negate_expr' => 'notWithinCustomObjects', - ], + 'label' => 'within custom objects', + 'expr' => 'withinCustomObjects', + 'negate_expr' => 'notWithinCustomObjects', + ], + ]; + + $betweenOperators = [ + 'between' => 'between', + 'not between' => '!between', ]; - $fieldOperators = [ + $fieldOperators = array_merge([ 'equals' => '=', 'not equal' => '!=', 'greater than' => 'gt', @@ -216,6 +249,136 @@ public function testOnGenerateSegmentFilters(): void 'less than or equal' => 'lte', 'empty' => 'empty', 'not empty' => '!empty', + ], $betweenOperators); + + $event = new LeadListFiltersChoicesEvent([], [], $this->translator); + + $this->configProvider->expects($this->once()) + ->method('pluginIsEnabled') + ->willReturn(true); + + $this->fieldTypeProvider->expects($this->once()) + ->method('getKeyTypeMapping') + ->willReturn($keyTypeMapping); + + $this->customObjectRepository->expects($this->once()) + ->method('matching') + ->with($criteria) + ->willReturn(new ArrayCollection([$customObject])); + + $translationsKeys = [ + ['custom.item.name.label'], + ['mautic.lead.list.form.operator.equals'], + ['mautic.lead.list.form.operator.notequals'], + ['mautic.lead.list.form.operator.isempty'], + ['mautic.lead.list.form.operator.isnotempty'], + ['mautic.lead.list.form.operator.islike'], + ['mautic.lead.list.form.operator.isnotlike'], + ['mautic.lead.list.form.operator.regexp'], + ['mautic.lead.list.form.operator.notregexp'], + ['mautic.core.operator.starts.with'], + ['mautic.core.operator.ends.with'], + ['mautic.core.operator.contains'], + ['mautic.lead.list.form.operator.equals'], + ['mautic.lead.list.form.operator.notequals'], + ['mautic.lead.list.form.operator.greaterthan'], + ['mautic.lead.list.form.operator.greaterthanequals'], + ['mautic.lead.list.form.operator.lessthan'], + ['mautic.lead.list.form.operator.lessthanequals'], + ['mautic.lead.list.form.operator.isempty'], + ['mautic.lead.list.form.operator.isnotempty'], + ['mautic.lead.list.form.operator.islike'], + ['mautic.lead.list.form.operator.isnotlike'], + ['mautic.lead.list.form.operator.between'], + ['mautic.lead.list.form.operator.notbetween'], + ['mautic.lead.list.form.operator.regexp'], + ['mautic.lead.list.form.operator.notregexp'], + ['mautic.core.operator.starts.with'], + ['mautic.core.operator.ends.with'], + ['mautic.core.operator.contains'], + ]; + + $translations = [ + 'Mobile', + 'equals', + 'not equal', + 'empty', + 'not empty', + 'like', + 'not like', + 'regexp', + 'not regexp', + 'starts with', + 'ends with', + 'contains', + 'equals', + 'not equal', + 'greater than', + 'greater than or equal', + 'less than', + 'less than or equal', + 'empty', + 'not empty', + 'like', + 'not like', + 'between', + 'not between', + 'regexp', + 'not regexp', + 'starts with', + 'ends with', + 'contains', + ]; + + $this->translator + ->method('trans') + ->withConsecutive(...$translationsKeys) + ->willReturn(...$translations); + + $this->filterOperatorProvider->expects($this->any()) + ->method('getAllOperators') + ->willReturn($allOperators); + + $this->subscriber->onGenerateSegmentFilters($event); + + $choices = $event->getChoices(); + $this->assertIsArray($choices); + $this->assertArrayHasKey('custom_object', $choices); + $this->assertArrayHasKey('cmo_1', $choices['custom_object']); + $this->assertArrayHasKey('cmf_1', $choices['custom_object']); + $this->assertSame('Products Mobile', $choices['custom_object']['cmo_1']['label']); + $this->assertSame('Products : Price', $choices['custom_object']['cmf_1']['label']); + $this->assertSame($fieldOperators, $choices['custom_object']['cmf_1']['operators']); + } + + public function testOnGenerateSegmentFiltersForDate(): void + { + if (!$this->isCloudProject()) { + $this->markTestSkipped('OVERRIDE_OPERATOR_LABEL_FOR_FIELD_TYPE event is not present in 4.4'); + } + + $customObject = new CustomObject(); + $customObject->setId(1); + $customObject->setNameSingular('Product'); + $customObject->setNamePlural('Products'); + $customObject->setIsPublished(true); + + $dateType = new DateType($this->translator, $this->filterOperatorProvider); + $dateCustomField = new CustomField(); + $dateCustomField->setId(2); + $dateCustomField->setType('date'); + $dateCustomField->setTypeObject($dateType); + $dateCustomField->setLabel('Purchase Date'); + $dateCustomField->setAlias('purchase_date'); + + $customObject->addCustomField($dateCustomField); + + $criteria = new Criteria(Criteria::expr()->eq('isPublished', 1)); + + $keyTypeMapping = [ + 'custom.field.type.text' => 'text', + 'custom.field.type.date' => 'date', + 'custom.field.type.hidden' => 'hidden', ]; $event = new LeadListFiltersChoicesEvent([], [], $this->translator); @@ -237,66 +400,94 @@ public function testOnGenerateSegmentFilters(): void ->method('trans') ->withConsecutive( ['custom.item.name.label'], - ['mautic.lead.list.form.operator.equals'], - ['mautic.lead.list.form.operator.notequals'], - ['mautic.lead.list.form.operator.isempty'], - ['mautic.lead.list.form.operator.isnotempty'], - ['mautic.lead.list.form.operator.islike'], - ['mautic.lead.list.form.operator.isnotlike'], - ['mautic.lead.list.form.operator.regexp'], - ['mautic.lead.list.form.operator.notregexp'], - ['mautic.core.operator.starts.with'], - ['mautic.core.operator.ends.with'], - ['mautic.core.operator.contains'], - ['mautic.lead.list.form.operator.equals'], - ['mautic.lead.list.form.operator.notequals'], - ['mautic.lead.list.form.operator.greaterthan'], - ['mautic.lead.list.form.operator.greaterthanequals'], - ['mautic.lead.list.form.operator.lessthan'], - ['mautic.lead.list.form.operator.lessthanequals'], - ['mautic.lead.list.form.operator.isempty'], - ['mautic.lead.list.form.operator.isnotempty'], - ['mautic.lead.list.form.operator.islike'], - ['mautic.lead.list.form.operator.isnotlike'], - ['mautic.lead.list.form.operator.regexp'], - ['mautic.lead.list.form.operator.notregexp'], - ['mautic.core.operator.starts.with'], - ['mautic.core.operator.ends.with'], - ['mautic.core.operator.contains'] ) ->willReturn( - 'Mobile', - 'equals', - 'not equal', - 'empty', - 'not empty', - 'like', - 'not like', - 'regexp', - 'not regexp', - 'starts with', - 'ends with', - 'contains', - 'equals', - 'not equal', - 'greater than', - 'greater than or equal', - 'less than', - 'less than or equal', - 'empty', - 'not empty', - 'like', - 'not like', - 'regexp', - 'not regexp', - 'starts with', - 'ends with', - 'contains' + 'Mobile' ); $this->filterOperatorProvider->expects($this->once()) ->method('getAllOperators') - ->willReturn($allOperators); + ->willReturn([ + OperatorOptions::GREATER_THAN => [ + 'label' => 'grater than', + 'expr' => 'gt', + 'negate_expr' => 'lt', + ], + OperatorOptions::GREATER_THAN_OR_EQUAL => [ + 'label' => 'grater than or equal', + 'expr' => 'gte', + 'negate_expr' => 'lt', + ], + OperatorOptions::LESS_THAN => [ + 'label' => 'less than', + 'expr' => 'lt', + 'negagte_expr' => 'gt', + ], + OperatorOptions::LESS_THAN_OR_EQUAL => [ + 'label' => 'less than or equal', + 'expr' => 'lte', + 'negate_expr' => 'gt', + ], + ]); + + $this->dispatcher->expects($this->exactly(3)) + ->method('dispatch') + ->withConsecutive( + [ + LeadEvents::COLLECT_OPERATORS_FOR_FIELD_TYPE, + $this->callback(function (TypeOperatorsEvent $event) { + // Emulate a subscriber. + $event->setOperatorsForFieldType('date', [ + 'include' => [ + OperatorOptions::GREATER_THAN, + OperatorOptions::GREATER_THAN_OR_EQUAL, + OperatorOptions::LESS_THAN, + OperatorOptions::LESS_THAN_OR_EQUAL, + ], + ]); + + $event->setOperatorsForFieldType('text', [ + 'include' => [ + OperatorOptions::GREATER_THAN, + OperatorOptions::GREATER_THAN_OR_EQUAL, + OperatorOptions::LESS_THAN, + OperatorOptions::LESS_THAN_OR_EQUAL, + ], + ]); + + return true; + }), + ], + [ + LeadEvents::OVERRIDE_OPERATOR_LABEL_FOR_FIELD_TYPE, + $this->callback(function (OverrideOperatorLabelEvent $event) { + // Emulate a subscriber. + $event->setTypeOperatorsChoices( + [ + 'Greater Than' => OperatorOptions::GREATER_THAN, + ] + ); + + return true; + }), + ], + [ + LeadEvents::OVERRIDE_OPERATOR_LABEL_FOR_FIELD_TYPE, + $this->callback(function (OverrideOperatorLabelEvent $event) { + // Emulate a subscriber. + $event->setTypeOperatorsChoices( + [ + 'After' => OperatorOptions::GREATER_THAN, + 'After (Including day)' => OperatorOptions::GREATER_THAN_OR_EQUAL, + 'Before' => OperatorOptions::LESS_THAN, + 'Before (Including day)' => OperatorOptions::LESS_THAN_OR_EQUAL, + ] + ); + + return true; + }), + ], + ); $this->subscriber->onGenerateSegmentFilters($event); @@ -304,10 +495,18 @@ public function testOnGenerateSegmentFilters(): void $this->assertIsArray($choices); $this->assertArrayHasKey('custom_object', $choices); $this->assertArrayHasKey('cmo_1', $choices['custom_object']); - $this->assertArrayHasKey('cmf_1', $choices['custom_object']); + $this->assertArrayHasKey('cmf_2', $choices['custom_object']); $this->assertSame('Products Mobile', $choices['custom_object']['cmo_1']['label']); - $this->assertSame('Products : Price', $choices['custom_object']['cmf_1']['label']); - $this->assertSame($fieldOperators, $choices['custom_object']['cmf_1']['operators']); + $this->assertSame('Products : Purchase Date', $choices['custom_object']['cmf_2']['label']); + $this->assertSame( + [ + 'After' => OperatorOptions::GREATER_THAN, + 'After (Including day)' => OperatorOptions::GREATER_THAN_OR_EQUAL, + 'Before' => OperatorOptions::LESS_THAN, + 'Before (Including day)' => OperatorOptions::LESS_THAN_OR_EQUAL, + ], + $choices['custom_object']['cmf_2']['operators'] + ); } public function testGetSubscribedEvents(): void diff --git a/Tests/Unit/EventListener/SerializerSubscriberTest.php b/Tests/Unit/EventListener/SerializerSubscriberTest.php index 5f607ce93..3e154b68c 100644 --- a/Tests/Unit/EventListener/SerializerSubscriberTest.php +++ b/Tests/Unit/EventListener/SerializerSubscriberTest.php @@ -27,7 +27,7 @@ use MauticPlugin\CustomObjectsBundle\Repository\CustomItemXrefContactRepository; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class SerializerSubscriberTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/EventListener/TokenSubscriberTest.php b/Tests/Unit/EventListener/TokenSubscriberTest.php index 62f2821be..775483ab5 100644 --- a/Tests/Unit/EventListener/TokenSubscriberTest.php +++ b/Tests/Unit/EventListener/TokenSubscriberTest.php @@ -7,6 +7,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\DBAL\Query\QueryBuilder; use Mautic\CampaignBundle\Entity\Campaign; +use Mautic\CampaignBundle\Entity\Event; use Mautic\CampaignBundle\Event\CampaignEvent; use Mautic\CampaignBundle\Model\EventModel; use Mautic\CoreBundle\Event\BuilderEvent; @@ -26,9 +27,11 @@ use MauticPlugin\CustomObjectsBundle\Event\CustomItemListDbalQueryEvent; use MauticPlugin\CustomObjectsBundle\EventListener\TokenSubscriber; use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; +use MauticPlugin\CustomObjectsBundle\Helper\FilterEvaluator; use MauticPlugin\CustomObjectsBundle\Helper\QueryFilterHelper; use MauticPlugin\CustomObjectsBundle\Helper\TokenFormatter; use MauticPlugin\CustomObjectsBundle\Helper\TokenParser; +use MauticPlugin\CustomObjectsBundle\Model\CustomFieldModel; use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel; use MauticPlugin\CustomObjectsBundle\Provider\ConfigProvider; @@ -36,7 +39,7 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class TokenSubscriberTest extends TestCase { @@ -65,6 +68,11 @@ class TokenSubscriberTest extends TestCase */ private $customItemModel; + /** + * @var CustomFieldModel|MockObject + */ + private $customFieldModel; + /** * @var TokenParser|MockObject */ @@ -85,6 +93,11 @@ class TokenSubscriberTest extends TestCase */ private $tokenFormatter; + /** + * @var FilterEvaluator|MockObject + */ + private $filterEvaluator; + /** * @var TokenSubscriber */ @@ -114,20 +127,25 @@ protected function setUp(): void $this->queryFilterFactory = $this->createMock(QueryFilterFactory::class); $this->customObjectModel = $this->createMock(CustomObjectModel::class); $this->customItemModel = $this->createMock(CustomItemModel::class); + $this->customFieldModel = $this->createMock(CustomFieldModel::class); $this->tokenParser = $this->createMock(TokenParser::class); $this->eventModel = $this->createMock(EventModel::class); $this->eventDispatcher = $this->createMock(EventDispatcher::class); $this->tokenFormatter = $this->createMock(TokenFormatter::class); + $this->filterEvaluator = $this->createMock(FilterEvaluator::class); $this->subscriber = new TokenSubscriber( $this->configProvider, $this->queryFilterHelper, $this->queryFilterFactory, $this->customObjectModel, $this->customItemModel, + $this->customFieldModel, $this->tokenParser, $this->eventModel, $this->eventDispatcher, - $this->tokenFormatter + $this->tokenFormatter, + $this->filterEvaluator, + 15 ); $this->builderEvent = $this->createMock(BuilderEvent::class); @@ -143,6 +161,7 @@ public function testGetSubscribedEvents(): void EmailEvents::EMAIL_ON_SEND => ['decodeTokens', 0], EmailEvents::EMAIL_ON_DISPLAY => ['decodeTokens', 0], CustomItemEvents::ON_CUSTOM_ITEM_LIST_DBAL_QUERY => ['onListQuery', -1], + EmailEvents::TOKEN_REPLACEMENT => ['onTokenReplacement', 100], ], TokenSubscriber::getSubscribedEvents() ); @@ -786,7 +805,7 @@ public function testOnListQueryForSegmentFilterWithCampaignEmailWhenNoSegmentExi $this->constructWithDependencies(); $queryBuilder = $this->createMock(QueryBuilder::class); - $campaignEvent = $this->createMock(CampaignEvent::class); + $campaignEvent = $this->createMock(Event::class); $token = $this->tokenParser->findTokens('{custom-object=product:sku | where=segment-filter |order=latest|limit=1 | default=No thing}')->current(); $campaign = $this->createMock(Campaign::class); @@ -844,10 +863,13 @@ private function constructWithDependencies(): void $this->queryFilterFactory, $this->customObjectModel, $this->customItemModel, + $this->customFieldModel, $this->tokenParser, $this->eventModel, $this->eventDispatcher, - new TokenFormatter() + new TokenFormatter(), + $this->createMock(FilterEvaluator::class), + 15 ); } } diff --git a/Tests/Unit/Form/Type/CampaignConditionFieldValueTypeTest.php b/Tests/Unit/Form/Type/CampaignConditionFieldValueTypeTest.php index c8df0e30e..8288c7e93 100644 --- a/Tests/Unit/Form/Type/CampaignConditionFieldValueTypeTest.php +++ b/Tests/Unit/Form/Type/CampaignConditionFieldValueTypeTest.php @@ -10,6 +10,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Form\Type\CampaignConditionFieldValueType; use MauticPlugin\CustomObjectsBundle\Model\CustomFieldModel; +use MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemRouteProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -19,7 +20,7 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormConfigBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; final class CampaignConditionFieldValueTypeTest extends TestCase { @@ -28,6 +29,11 @@ final class CampaignConditionFieldValueTypeTest extends TestCase */ private $customFieldModelMock; + /** + * @var MockObject|CustomObjectModel + */ + private $customObjectModelMock; + /** * @var MockObject|CustomItemRouteProvider */ @@ -48,10 +54,12 @@ protected function setUp(): void parent::setUp(); $this->customFieldModelMock = $this->createMock(CustomFieldModel::class); + $this->customObjectModelMock = $this->createMock(CustomObjectModel::class); $this->customItemRouterMock = $this->createMock(CustomItemRouteProvider::class); $this->translatorMock = $this->createMock(TranslatorInterface::class); $this->campaignConditionFieldValueType = new CampaignConditionFieldValueType( $this->customFieldModelMock, + $this->customObjectModelMock, $this->customItemRouterMock, $this->translatorMock ); @@ -80,6 +88,11 @@ public function testBuildForm(): void $customField->setTypeObject(new IntType($this->translatorMock, $filterOperatorProviderInterfaceMock)); $customFields = [42 => $customField]; + $this->customObjectModelMock + ->expects(self::once()) + ->method('fetchEntity') + ->with($customObject->getId()) + ->willReturn($customObject); $this->customFieldModelMock ->expects(self::once()) ->method('fetchCustomFieldsForObject') @@ -102,7 +115,7 @@ public function testBuildForm(): void 'class' => 'form-control', ], 'choice_attr' => [ - 42 => [ + 'Cheese' => [ 'data-operators' => '{"=":"a","!=":"b"}', 'data-options' => '[]', 'data-field-type' => 'int', @@ -139,8 +152,8 @@ public function testBuildForm(): void ] ); $options = [ - 'customObject' => $customObject, - 'data' => [ + 'customObjectId' => $customObject->getId(), + 'data' => [ 'field' => 42, ], ]; @@ -160,7 +173,7 @@ public function testConfigureOptions() $resolver ->expects(self::once()) ->method('setRequired') - ->with(['customObject']); + ->with(['customObjectId']); $this->campaignConditionFieldValueType->configureOptions($resolver); } diff --git a/Tests/Unit/Form/Type/CustomFieldTypeTest.php b/Tests/Unit/Form/Type/CustomFieldTypeTest.php index 789229922..37b3e389a 100644 --- a/Tests/Unit/Form/Type/CustomFieldTypeTest.php +++ b/Tests/Unit/Form/Type/CustomFieldTypeTest.php @@ -4,7 +4,6 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Form\Type; -use Mautic\CoreBundle\Form\Type\FormButtonsType; use Mautic\CoreBundle\Form\Type\YesNoButtonGroupType; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomFieldFactory; @@ -66,6 +65,7 @@ public function testBuildModalFormFields(): void { $options['data'] = $this->customField; $options['custom_object_form'] = ''; + $options['action'] = ''; $this->formBuilder->expects($this->once()) ->method('addModelTransFormer') @@ -160,9 +160,9 @@ public function testBuildModalFormFields(): void 'label' => 'custom.field.is_unique_identifier.label', 'attr' => [ 'data-toggle-button' => true, - 'tooltip' => 'custom.field.help.is_unique_identifier' + 'tooltip' => 'custom.field.help.is_unique_identifier', ], - ] + ], ] ); diff --git a/Tests/Unit/Form/Validator/AllowUniqueIdentifierTest.php b/Tests/Unit/Form/Validator/AllowUniqueIdentifierTest.php index c5271f759..90a44a140 100644 --- a/Tests/Unit/Form/Validator/AllowUniqueIdentifierTest.php +++ b/Tests/Unit/Form/Validator/AllowUniqueIdentifierTest.php @@ -27,4 +27,4 @@ public function testGetTargets(): void { $this->assertSame(AllowUniqueIdentifier::CLASS_CONSTRAINT, $this->constraint->getTargets()); } -} \ No newline at end of file +} diff --git a/Tests/Unit/Form/Validator/AllowUniqueIdentifierValidatorTest.php b/Tests/Unit/Form/Validator/AllowUniqueIdentifierValidatorTest.php index c276abae4..e4ce50e8f 100644 --- a/Tests/Unit/Form/Validator/AllowUniqueIdentifierValidatorTest.php +++ b/Tests/Unit/Form/Validator/AllowUniqueIdentifierValidatorTest.php @@ -4,9 +4,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; -use MauticPlugin\CustomObjectsBundle\Form\Validator\Constraints\AllowUniqueIdentifier; use MauticPlugin\CustomObjectsBundle\Form\Validator\Constraints\AllowUniqueIdentifierValidator; -use MauticPlugin\CustomObjectsBundle\Model\CustomFieldModel; use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository; use PHPUnit\Framework\MockObject\MockObject; @@ -105,6 +103,10 @@ public function testAllowIsUniqueIdentifierInvalid(): void ->method('addViolation'); /** @phpstan-ignore-next-line */ + $this->constraint->method('__get') + ->with('message') + ->willReturn('custom.field.allow.unique_identifier.invalid'); + $message = $this->constraint->message; $this->context->expects($this->once()) ->method('buildViolation') diff --git a/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php b/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php index 63f1943a2..78e83912f 100644 --- a/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php +++ b/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php @@ -86,6 +86,10 @@ public function testValidateNoCustomObject() $violationBuilder->expects($this->once()) ->method('addViolation'); + $this->constraint->method('__get') + ->with('missingMasterObject') + ->willReturn("Objects of type 'Relationship' must select a master object."); + $this->context->expects($this->once()) ->method('buildViolation') ->with($this->constraint->missingMasterObject) diff --git a/Tests/Unit/Helper/ContactFilterMatcherTest.php b/Tests/Unit/Helper/ContactFilterMatcherTest.php new file mode 100644 index 000000000..eef34aee4 --- /dev/null +++ b/Tests/Unit/Helper/ContactFilterMatcherTest.php @@ -0,0 +1,309 @@ +customFieldModel = $this->createMock(CustomFieldModel::class); + $this->customObjectModel = $this->createMock(CustomObjectModel::class); + $this->customItemModel = $this->createMock(CustomItemModel::class); + $this->companyRepository = $this->createMock(CompanyRepository::class); + $this->connection = $this->createMock(Connection::class); + + $this->matcher = new ContactFilterMatcher( + $this->customFieldModel, + $this->customObjectModel, + $this->customItemModel, + $this->companyRepository, + $this->connection, + new FilterEvaluator(), + 10 + ); + } + + public function testMatchReturnsFalseWhenNoCustomObjectFiltersPresent(): void + { + $filters = [ + $this->buildLeadFilter('email', '=', 'test@example.com'), + ]; + + $hasCustomFields = false; + $result = $this->matcher->match($filters, ['id' => 1, 'email' => 'test@example.com'], $hasCustomFields); + + $this->assertFalse($result); + $this->assertFalse($hasCustomFields); + $this->customObjectModel->expects($this->never())->method('fetchEntity'); + } + + public function testMatchReturnsFalseWhenCustomObjectFetchThrowsNotFoundException(): void + { + $this->customObjectModel->method('fetchEntity') + ->willThrowException(new NotFoundException('Custom object not found')); + + $hasCustomFields = false; + $result = $this->matcher->match([$this->buildCmoFilter('cmo_1', '=', 'Acme')], ['id' => 42], $hasCustomFields); + + $this->assertFalse($result); + $this->assertFalse($hasCustomFields); + } + + public function testMatchReturnsFalseWhenCustomObjectFetchThrowsInvalidCustomObjectFormatListException(): void + { + $this->customObjectModel->method('fetchEntity') + ->willThrowException(new InvalidCustomObjectFormatListException('bad format')); + + $hasCustomFields = false; + $result = $this->matcher->match([$this->buildCmoFilter('cmo_1', '=', 'Acme')], ['id' => 42], $hasCustomFields); + + $this->assertFalse($result); + $this->assertFalse($hasCustomFields); + } + + public function testMatchReturnsFalseWhenContactHasNoLinkedCustomItems(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(5)); + $this->customItemModel->method('getArrayTableData')->willReturn([]); + + $hasCustomFields = false; + $result = $this->matcher->match([$this->buildCmoFilter('cmo_5', '=', 'Acme')], ['id' => 42], $hasCustomFields); + + $this->assertFalse($result); + // hasCustomFields is true because the CO filter was found and processed + $this->assertTrue($hasCustomFields); + } + + public function testMatchReturnsTrueForEmptyOperatorWhenContactHasNoLinkedItems(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(1)); + $this->customItemModel->method('getArrayTableData')->willReturn([]); + + $filter = array_merge($this->buildCmoFilter('cmo_1', 'empty', ''), ['type' => 'text']); + $result = $this->matcher->match([$filter], ['id' => 42]); + + $this->assertTrue($result); + } + + public function testMatchReturnsFalseForNotEmptyOperatorWhenContactHasNoLinkedItems(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(1)); + $this->customItemModel->method('getArrayTableData')->willReturn([]); + + $filter = array_merge($this->buildCmoFilter('cmo_1', '!empty', ''), ['type' => 'text']); + $result = $this->matcher->match([$filter], ['id' => 42]); + + $this->assertFalse($result); + } + + public function testMatchReturnsTrueWhenItemNameMatchesEqualFilter(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(3)); + $this->customItemModel->method('getArrayTableData')->willReturn([['name' => 'Acme Corp']]); + + $result = $this->matcher->match([$this->buildCmoFilter('cmo_3', '=', 'Acme Corp')], ['id' => 42]); + + $this->assertTrue($result); + } + + public function testMatchReturnsFalseWhenItemNameDoesNotMatchEqualFilter(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(3)); + $this->customItemModel->method('getArrayTableData')->willReturn([['name' => 'Wrong Corp']]); + + $result = $this->matcher->match([$this->buildCmoFilter('cmo_3', '=', 'Acme Corp')], ['id' => 42]); + + $this->assertFalse($result); + } + + public function testMatchReturnsTrueWhenAnyLinkedItemNameMatchesFilter(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(3)); + $this->customItemModel->method('getArrayTableData')->willReturn([ + ['name' => 'First Item'], + ['name' => 'Acme Corp'], + ['name' => 'Third Item'], + ]); + + $result = $this->matcher->match([$this->buildCmoFilter('cmo_3', '=', 'Acme Corp')], ['id' => 42]); + + $this->assertTrue($result); + } + + public function testMatchSetsHasCustomFieldsToTrueWhenCustomObjectFilterIsProcessed(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(1)); + $this->customItemModel->method('getArrayTableData')->willReturn([['name' => 'Any']]); + + $hasCustomFields = false; + $this->matcher->match([$this->buildCmoFilter('cmo_1', '=', 'Any')], ['id' => 42], $hasCustomFields); + + $this->assertTrue($hasCustomFields); + } + + public function testCustomItemsAreFetchedOncePerObjectAndLeadAcrossMultipleFilters(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(1)); + + $this->customItemModel->expects($this->once()) + ->method('getArrayTableData') + ->willReturn([['name' => 'Acme']]); + + $filters = [ + $this->buildCmoFilter('cmo_1', '=', 'Acme'), + $this->buildCmoFilter('cmo_1', '!=', 'Other'), + ]; + + $this->matcher->match($filters, ['id' => 42]); + } + + public function testMatchFetchesCompanyDataWhenFilterFieldStartsWithCompany(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(1)); + $this->customItemModel->method('getArrayTableData')->willReturn([['name' => 'Test']]); + + $this->companyRepository->expects($this->once()) + ->method('getCompaniesByLeadId') + ->with('42') + ->willReturn([]); + + $filters = [ + $this->buildCmoFilter('cmo_1', '=', 'Test'), + $this->buildLeadFilter('companycountry', '=', 'US'), + ]; + + $this->matcher->match($filters, ['id' => 42]); + } + + public function testMatchDoesNotFetchCompanyDataWhenLeadAlreadyHasCompanies(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(1)); + $this->customItemModel->method('getArrayTableData')->willReturn([['name' => 'Test']]); + + $this->companyRepository->expects($this->never())->method('getCompaniesByLeadId'); + + $filters = [ + $this->buildCmoFilter('cmo_1', '=', 'Test'), + $this->buildLeadFilter('companycountry', '=', 'US'), + ]; + + $this->matcher->match($filters, ['id' => 42, 'companies' => [['companycountry' => 'US']]]); + } + + public function testMatchFetchesTagsWhenFilterTypeIsTags(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(1)); + $this->customItemModel->method('getArrayTableData')->willReturn([['name' => 'Test']]); + + $result = $this->createMock(Result::class); + $queryBuilder = $this->createMock(DbalQueryBuilder::class); + $result->method('fetchFirstColumn')->willReturn(['1', '5']); + $queryBuilder->method('select')->willReturnSelf(); + $queryBuilder->method('from')->willReturnSelf(); + $queryBuilder->method('where')->willReturnSelf(); + $queryBuilder->method('setParameter')->willReturnSelf(); + $queryBuilder->method('executeQuery')->willReturn($result); + + $this->connection->expects($this->once()) + ->method('createQueryBuilder') + ->willReturn($queryBuilder); + + $filters = [ + $this->buildCmoFilter('cmo_1', '=', 'Test'), + ['object' => 'lead', 'field' => 'tags', 'type' => 'tags', 'operator' => 'in', 'filter' => ['1'], 'glue' => 'and'], + ]; + + $this->matcher->match($filters, ['id' => 42]); + } + + public function testMatchDoesNotFetchTagsWhenLeadAlreadyHasTags(): void + { + $this->customObjectModel->method('fetchEntity')->willReturn($this->buildCustomObject(1)); + $this->customItemModel->method('getArrayTableData')->willReturn([['name' => 'Test']]); + + $this->connection->expects($this->never())->method('createQueryBuilder'); + + $filters = [ + $this->buildCmoFilter('cmo_1', '=', 'Test'), + ['object' => 'lead', 'field' => 'tags', 'type' => 'tags', 'operator' => 'in', 'filter' => ['1'], 'glue' => 'and'], + ]; + + $this->matcher->match($filters, ['id' => 42, 'tags' => ['1', '5']]); + } + + // Helpers + + private function buildCustomObject(int $id): MockObject + { + $customObject = $this->createMock(CustomObject::class); + $customObject->method('getId')->willReturn($id); + + return $customObject; + } + + /** + * @return mixed[] + */ + private function buildCmoFilter(string $field, string $operator, string $filterValue): array + { + return [ + 'object' => 'custom_object', + 'field' => $field, + 'type' => 'text', + 'operator' => $operator, + 'filter' => $filterValue, + 'glue' => 'and', + ]; + } + + /** + * @return mixed[] + */ + private function buildLeadFilter(string $field, string $operator, string $filterValue): array + { + return [ + 'object' => 'lead', + 'field' => $field, + 'type' => 'text', + 'operator' => $operator, + 'filter' => $filterValue, + 'glue' => 'and', + ]; + } +} diff --git a/Tests/Unit/Helper/FilterEvaluatorTest.php b/Tests/Unit/Helper/FilterEvaluatorTest.php new file mode 100644 index 000000000..8dfcf4b5d --- /dev/null +++ b/Tests/Unit/Helper/FilterEvaluatorTest.php @@ -0,0 +1,364 @@ +evaluator = new FilterEvaluator(); + } + + // ------------------------------------------------------------------------- + // Guard conditions + // ------------------------------------------------------------------------- + + public function testReturnsFalseWhenLeadHasNoId(): void + { + $filters = [$this->leadFilter('email', 'text', '=', 'test@example.com')]; + $this->assertFalse($this->evaluator->evaluate($filters, ['email' => 'test@example.com'])); + } + + public function testReturnsFalseWhenFiltersAreEmpty(): void + { + $this->assertFalse($this->evaluator->evaluate([], ['id' => 1])); + } + + public function testSkipsFilterWhenFieldNotPresentInLead(): void + { + // Filter references a field that is not in $lead — should be skipped, result is false. + $filters = [$this->leadFilter('missing_field', 'text', '=', 'value')]; + $this->assertFalse($this->evaluator->evaluate($filters, ['id' => 1])); + } + + // ------------------------------------------------------------------------- + // AND / OR group logic + // ------------------------------------------------------------------------- + + public function testAndFiltersAllMustBeTrue(): void + { + $filters = [ + $this->leadFilter('first_name', 'text', '=', 'Alice'), + $this->leadFilter('last_name', 'text', '=', 'Smith'), + ]; + + $this->assertTrue( + $this->evaluator->evaluate($filters, ['id' => 1, 'first_name' => 'Alice', 'last_name' => 'Smith']) + ); + + $this->assertFalse( + $this->evaluator->evaluate($filters, ['id' => 1, 'first_name' => 'Alice', 'last_name' => 'Jones']) + ); + } + + public function testOrGroupPassesWhenFirstGroupFails(): void + { + $filters = [ + $this->leadFilter('email', 'text', '=', 'wrong@example.com'), + array_merge($this->leadFilter('city', 'text', '=', 'Paris'), ['glue' => 'or']), + ]; + + $lead = ['id' => 1, 'email' => 'test@example.com', 'city' => 'Paris']; + $this->assertTrue($this->evaluator->evaluate($filters, $lead)); + } + + public function testOrGroupPassesWhenFirstGroupPasses(): void + { + $filters = [ + $this->leadFilter('email', 'text', '=', 'test@example.com'), + array_merge($this->leadFilter('city', 'text', '=', 'Wrong'), ['glue' => 'or']), + ]; + + $lead = ['id' => 1, 'email' => 'test@example.com', 'city' => 'Paris']; + $this->assertTrue($this->evaluator->evaluate($filters, $lead)); + } + + public function testReturnsFalseWhenAllOrGroupsFail(): void + { + $filters = [ + $this->leadFilter('email', 'text', '=', 'wrong@example.com'), + array_merge($this->leadFilter('city', 'text', '=', 'Wrong'), ['glue' => 'or']), + ]; + + $lead = ['id' => 1, 'email' => 'test@example.com', 'city' => 'Paris']; + $this->assertFalse($this->evaluator->evaluate($filters, $lead)); + } + + // ------------------------------------------------------------------------- + // Custom object any-match semantics + // ------------------------------------------------------------------------- + + public function testCustomObjectAnyItemMatchWins(): void + { + $filters = [$this->cmoFilter('cmf_1', 'text', '=', 'premium')]; + $lead = ['id' => 1, 'cmf_1' => ['basic', 'premium', 'trial']]; + + $this->assertTrue($this->evaluator->evaluate($filters, $lead)); + } + + public function testCustomObjectReturnsFalseWhenNoItemMatches(): void + { + $filters = [$this->cmoFilter('cmf_1', 'text', '=', 'enterprise')]; + $lead = ['id' => 1, 'cmf_1' => ['basic', 'premium']]; + + $this->assertFalse($this->evaluator->evaluate($filters, $lead)); + } + + public function testCustomObjectEmptyOperatorMatchesWhenNoLinkedItems(): void + { + $filters = [$this->cmoFilter('cmf_1', 'text', 'empty', null)]; + $lead = ['id' => 1, 'cmf_1' => []]; + + $this->assertTrue($this->evaluator->evaluate($filters, $lead)); + } + + public function testCustomObjectNotEmptyOperatorFailsWhenNoLinkedItems(): void + { + $filters = [$this->cmoFilter('cmf_1', 'text', '!empty', null)]; + $lead = ['id' => 1, 'cmf_1' => []]; + + $this->assertFalse($this->evaluator->evaluate($filters, $lead)); + } + + public function testCustomObjectScalarValueIsWrappedInArray(): void + { + // cmf_ value stored as scalar rather than array — evaluator must normalise it. + $filters = [$this->cmoFilter('cmf_1', 'text', '=', 'hello')]; + $lead = ['id' => 1, 'cmf_1' => 'hello']; + + $this->assertTrue($this->evaluator->evaluate($filters, $lead)); + } + + // ------------------------------------------------------------------------- + // Operators — string/text + // ------------------------------------------------------------------------- + + public function testEqualOperator(): void + { + $this->assertOperator('text', '=', 'abc', 'abc', true); + $this->assertOperator('text', '=', 'abc', 'xyz', false); + } + + public function testNotEqualOperator(): void + { + $this->assertOperator('text', '!=', 'abc', 'xyz', true); + $this->assertOperator('text', '!=', 'abc', 'abc', false); + } + + public function testEmptyOperator(): void + { + $this->assertOperator('text', 'empty', '', null, true); + $this->assertOperator('text', 'empty', 'value', null, false); + } + + public function testNotEmptyOperator(): void + { + $this->assertOperator('text', '!empty', 'value', null, true); + $this->assertOperator('text', '!empty', '', null, false); + } + + public function testLikeOperatorWithPercentWildcard(): void + { + $this->assertOperator('text', 'like', 'abracadabra', 'abra%', true); + $this->assertOperator('text', 'like', 'abracadabra', '%cadabra', true); + $this->assertOperator('text', 'like', 'abracadabra', '%cada%', true); + $this->assertOperator('text', 'like', 'abracadabra', 'unicorn%', false); + } + + public function testNotLikeOperator(): void + { + $this->assertOperator('text', '!like', 'abracadabra', 'unicorn%', true); + $this->assertOperator('text', '!like', 'abracadabra', 'abra%', false); + } + + public function testStartsWithOperator(): void + { + $this->assertOperator('text', 'startsWith', 'abracadabra', 'abra', true); + $this->assertOperator('text', 'startsWith', 'abracadabra', 'cadabra', false); + } + + public function testEndsWithOperator(): void + { + $this->assertOperator('text', 'endsWith', 'abracadabra', 'cadabra', true); + $this->assertOperator('text', 'endsWith', 'abracadabra', 'unicorn', false); + } + + public function testContainsOperator(): void + { + $this->assertOperator('text', 'contains', 'abracadabra', 'cada', true); + $this->assertOperator('text', 'contains', 'abracadabra', 'unicorn', false); + } + + public function testRegexpOperator(): void + { + $this->assertOperator('text', 'regexp', 'abracadabra', 'abra.*cadabra', true); + $this->assertOperator('text', 'regexp', 'abracadabra', '^unicorn', false); + // Regexp is case-insensitive + $this->assertOperator('text', 'regexp', 'HELLO', 'hello', true); + } + + public function testNotRegexpOperator(): void + { + $this->assertOperator('text', '!regexp', 'abracadabra', '^unicorn', true); + $this->assertOperator('text', '!regexp', 'abracadabra', 'abra.*cadabra', false); + } + + public function testInOperator(): void + { + $this->assertOperator('text', 'in', 'b', ['a', 'b', 'c'], true); + $this->assertOperator('text', 'in', 'z', ['a', 'b', 'c'], false); + } + + public function testNotInOperator(): void + { + $this->assertOperator('text', '!in', 'z', ['a', 'b', 'c'], true); + $this->assertOperator('text', '!in', 'b', ['a', 'b', 'c'], false); + } + + public function testUnknownOperatorThrowsException(): void + { + $this->expectException(OperatorsNotFoundException::class); + + $filters = [$this->leadFilter('email', 'text', 'nonexistent_operator', 'value')]; + $this->evaluator->evaluate($filters, ['id' => 1, 'email' => 'test@example.com']); + } + + // ------------------------------------------------------------------------- + // Operators — comparison (number type) + // ------------------------------------------------------------------------- + + public function testGtOperator(): void + { + $this->assertOperator('number', 'gt', 10, 5, true); + $this->assertOperator('number', 'gt', 5, 10, false); + $this->assertOperator('number', 'gt', 5, 5, false); + } + + public function testGteOperator(): void + { + $this->assertOperator('number', 'gte', 10, 5, true); + $this->assertOperator('number', 'gte', 5, 5, true); + $this->assertOperator('number', 'gte', 4, 5, false); + } + + public function testLtOperator(): void + { + $this->assertOperator('number', 'lt', 3, 5, true); + $this->assertOperator('number', 'lt', 5, 5, false); + $this->assertOperator('number', 'lt', 10, 5, false); + } + + public function testLteOperator(): void + { + $this->assertOperator('number', 'lte', 3, 5, true); + $this->assertOperator('number', 'lte', 5, 5, true); + $this->assertOperator('number', 'lte', 10, 5, false); + } + + // ------------------------------------------------------------------------- + // Type coercions + // ------------------------------------------------------------------------- + + public function testBooleanCoercionEqualTrueValues(): void + { + // String '1' and int 1 are both coerced to true before comparison. + $this->assertOperator('boolean', '=', '1', 1, true); + $this->assertOperator('boolean', '=', '0', 0, true); + $this->assertOperator('boolean', '=', '1', 0, false); + } + + public function testBooleanStrictNotEqualUsesIdentity(): void + { + // For boolean type != uses strict identity after coercion. + $this->assertOperator('boolean', '!=', '1', 0, true); + $this->assertOperator('boolean', '!=', '0', 0, false); + } + + public function testMultiselectCoercionSplitsByPipe(): void + { + // Pipe-separated string is split into an array before in-check. + $this->assertOperator('multiselect', 'in', 'a|b|c', ['b'], true); + $this->assertOperator('multiselect', 'in', 'a|b|c', ['z'], false); + } + + public function testSelectCoercionSplitsByPipe(): void + { + $this->assertOperator('select', 'in', 'a|b', ['a'], true); + } + + public function testDatetimeCoercionAppendsMissingSeconds(): void + { + // Lead value has H:i:s, filter only H:i — evaluator appends :00 to filter. + $this->assertOperator('datetime', '=', '2024-01-01 12:00:00', '2024-01-01 12:00', true); + } + + public function testNumberCoercionConvertsToInt(): void + { + // String '42' in lead and int 42 as filter — both coerced to int. + $this->assertOperator('number', '=', '42', 42, true); + // 'int' is the custom field type key — same coercion applies. + $this->assertOperator('int', '=', '42', 42, true); + } + + // ------------------------------------------------------------------------- + // Helpers + // ------------------------------------------------------------------------- + + /** + * @param mixed $leadValue + * @param mixed $filterValue + */ + private function assertOperator(string $type, string $operator, $leadValue, $filterValue, bool $expected): void + { + $filters = [$this->leadFilter('field', $type, $operator, $filterValue)]; + $result = $this->evaluator->evaluate($filters, ['id' => 1, 'field' => $leadValue]); + + $this->assertSame( + $expected, + $result, + "Operator '{$operator}' (type: {$type}): lead=".json_encode($leadValue).' filter='.json_encode($filterValue) + ); + } + + /** + * @param mixed $filterValue + * + * @return array + */ + private function leadFilter(string $field, string $type, string $operator, $filterValue): array + { + return [ + 'glue' => 'and', + 'field' => $field, + 'object' => 'lead', + 'type' => $type, + 'filter' => $filterValue, + 'operator' => $operator, + ]; + } + + /** + * @param mixed $filterValue + * + * @return array + */ + private function cmoFilter(string $field, string $type, string $operator, $filterValue): array + { + return [ + 'glue' => 'and', + 'field' => $field, + 'object' => 'custom_object', + 'type' => $type, + 'filter' => $filterValue, + 'operator' => $operator, + ]; + } +} diff --git a/Tests/Unit/Helper/LockFlashMessageHelperTest.php b/Tests/Unit/Helper/LockFlashMessageHelperTest.php index 9d6d1bd40..ea1d8aae8 100644 --- a/Tests/Unit/Helper/LockFlashMessageHelperTest.php +++ b/Tests/Unit/Helper/LockFlashMessageHelperTest.php @@ -10,7 +10,7 @@ use MauticPlugin\CustomObjectsBundle\Helper\LockFlashMessageHelper; use PHPUnit\Framework\TestCase; use Symfony\Component\Routing\Router; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class LockFlashMessageHelperTest extends TestCase { @@ -76,7 +76,7 @@ public function testAddFlash(): void $checkedOut ->method('format') ->withConsecutive([$dateFormat1], [$dateFormat2], [$dateFormat3]) - ->willReturnOnConsecutiveCalls(1, 2, 3); + ->willReturnOnConsecutiveCalls('1', '2', '3'); $flashBag->expects($this->once()) ->method('add') diff --git a/Tests/Unit/Helper/QueryFilterFactoryTest.php b/Tests/Unit/Helper/QueryFilterFactoryTest.php index 9ff200554..603795971 100644 --- a/Tests/Unit/Helper/QueryFilterFactoryTest.php +++ b/Tests/Unit/Helper/QueryFilterFactoryTest.php @@ -26,14 +26,12 @@ class QueryFilterFactoryTest extends TestCase */ private $segmentFilter; - private string $prefix = ''; + private ?string $prefix = ''; public function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', '___'); - $this->prefix = MAUTIC_TABLE_PREFIX; $this->segmentFilter = $this->createMock(ContactSegmentFilter::class); @@ -199,6 +197,7 @@ private function trimSpacesAndLinebreaks(string $string): string { // Remove line breaks $string = preg_replace('/[\r\n]+/', ' ', $string); + // Remove multi-spaces return preg_replace('!\s+!', ' ', $string); } diff --git a/Tests/Unit/Helper/QueryFilterHelperTest.php b/Tests/Unit/Helper/QueryFilterHelperTest.php index b1da3be6c..1fd415595 100644 --- a/Tests/Unit/Helper/QueryFilterHelperTest.php +++ b/Tests/Unit/Helper/QueryFilterHelperTest.php @@ -8,6 +8,7 @@ use Doctrine\ORM\EntityManager; use Mautic\LeadBundle\Segment\Query\Expression\ExpressionBuilder; use Mautic\LeadBundle\Segment\Query\QueryBuilder; +use Mautic\LeadBundle\Segment\RandomParameterName; use MauticPlugin\CustomObjectsBundle\Helper\QueryFilterFactory; use MauticPlugin\CustomObjectsBundle\Helper\QueryFilterHelper; use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider; @@ -49,7 +50,8 @@ protected function setUp(): void $this->createMock(CustomFieldRepository::class), new QueryFilterFactory\Calculator(), 1 - ) + ), + new RandomParameterName() ); $this->queryBuilder = $this->createMock(QueryBuilder::class); $this->expressionBuilder = $this->createMock(ExpressionBuilder::class); @@ -78,7 +80,7 @@ public function testAddCustomObjectNameExpression(): void $this->queryBuilder ->expects($this->any()) ->method('setParameter') - ->with('test_value_value', 'acquia', null); + ->with('par0', 'acquia', null); $this->queryFilterHelper ->addCustomObjectNameExpression($this->queryBuilder, 'test', 'eq', 'acquia'); diff --git a/Tests/Unit/Model/CustomFieldOptionModelTest.php b/Tests/Unit/Model/CustomFieldOptionModelTest.php index 719d7c1f6..15ee572c6 100644 --- a/Tests/Unit/Model/CustomFieldOptionModelTest.php +++ b/Tests/Unit/Model/CustomFieldOptionModelTest.php @@ -24,8 +24,6 @@ protected function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); - $this->entityManager = $this->createMock(EntityManager::class); $this->connection = $this->createMock(Connection::class); $this->queryBuilder = $this->createMock(QueryBuilder::class); diff --git a/Tests/Unit/Model/CustomFieldValueModelTest.php b/Tests/Unit/Model/CustomFieldValueModelTest.php index ea70cf92d..4996f40c9 100644 --- a/Tests/Unit/Model/CustomFieldValueModelTest.php +++ b/Tests/Unit/Model/CustomFieldValueModelTest.php @@ -7,6 +7,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\QueryBuilder; +use Doctrine\DBAL\Result; use Doctrine\DBAL\Statement; use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\EntityManager; @@ -18,9 +19,9 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Model\CustomFieldValueModel; -use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomFieldValueModelTest extends \PHPUnit\Framework\TestCase { @@ -41,8 +42,6 @@ protected function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); - $this->customObject = $this->createMock(CustomObject::class); $this->customItem = $this->createMock(CustomItem::class); $this->customField = $this->createMock(CustomField::class); @@ -66,7 +65,7 @@ public function testGetValuesForItemIfItemDoesNotHaveId(): void { $customFields = new ArrayCollection([$this->customField]); - $this->customItem->expects($this->once()) + $this->customItem->expects($this->any()) ->method('getCustomObject') ->willReturn($this->customObject); @@ -177,11 +176,14 @@ public function testGetValuesForItemIfItemHasId(): void ->with('THE TEXT FIELD SQL QUERY UNION ALL THE NUMBER FIELD SQL QUERY') ->willReturn($this->statement); - $this->statement->expects($this->once()) - ->method('execute'); + $result = $this->createMock(Result::class); $this->statement->expects($this->once()) - ->method('fetchAll') + ->method('executeQuery') + ->willReturn($result); + + $result->expects($this->once()) + ->method('fetchAllAssociative') ->willReturn([[ 'custom_field_id' => 44, 'custom_item_id' => 33, @@ -248,7 +250,7 @@ public function testSaveForExistingCustomItem(): void $this->customItem->expects($this->exactly(2)) ->method('getId') - ->willReturn(null); + ->willReturn(0); $this->entityManager->expects($this->once()) ->method('persist') diff --git a/Tests/Unit/Model/CustomItemImportModelTest.php b/Tests/Unit/Model/CustomItemImportModelTest.php index 17aca122e..8ef2eeaa1 100644 --- a/Tests/Unit/Model/CustomItemImportModelTest.php +++ b/Tests/Unit/Model/CustomItemImportModelTest.php @@ -6,12 +6,20 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\EntityManager; -use Mautic\CoreBundle\Templating\Helper\FormatterHelper; +use Mautic\CoreBundle\Helper\CoreParametersHelper; +use Mautic\CoreBundle\Helper\UserHelper; +use Mautic\CoreBundle\Security\Permissions\CorePermissions; +use Mautic\CoreBundle\Translation\Translator; +use Mautic\CoreBundle\Twig\Helper\DateHelper; +use Mautic\CoreBundle\Twig\Helper\FormatterHelper; use Mautic\LeadBundle\Entity\Import; +use Mautic\LeadBundle\Entity\Lead; +use Mautic\LeadBundle\Entity\LeadRepository; use Mautic\LeadBundle\Provider\FilterOperatorProviderInterface; use Mautic\UserBundle\Entity\User; use MauticPlugin\CustomObjectsBundle\CustomFieldType\DateTimeType; use MauticPlugin\CustomObjectsBundle\CustomFieldType\TextareaType; +use MauticPlugin\CustomObjectsBundle\DTO\ImportLogDTO; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomFieldValueInterface; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; @@ -20,7 +28,9 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomItemImportModel; use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use PHPUnit\Framework\MockObject\MockObject; -use Symfony\Component\Translation\TranslatorInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class CustomItemImportModelTest extends \PHPUnit\Framework\TestCase { @@ -54,14 +64,48 @@ class CustomItemImportModelTest extends \PHPUnit\Framework\TestCase private $entityManager; /** - * @var MockObject|CustomItemModel + * @var MockObject|CorePermissions */ - private $customItemModel; + private $security; + + /** + * @var MockObject|EventDispatcherInterface + */ + private $dispatcher; + + /** + * @var MockObject|UrlGeneratorInterface + */ + private $router; + + /** + * @var MockObject|Translator + */ + private $translator; + + /** + * @var MockObject|UserHelper + */ + private $userHelper; + + /** + * @var MockObject|LoggerInterface + */ + private $logger; + + /** + * @var MockObject|CoreParametersHelper + */ + private $coreParametersHelper; + + private DateHelper $dateHelper; /** - * @var MockObject|FormatterHelper + * @var MockObject|CustomItemModel */ - private $formatterHelper; + private $customItemModel; + + private FormatterHelper $formatterHelper; /** * @var MockObject|CustomField @@ -93,23 +137,51 @@ protected function setUp(): void $this->import = $this->createMock(Import::class); $this->customItemModel = $this->createMock(CustomItemModel::class); $this->entityManager = $this->createMock(EntityManager::class); - $this->formatterHelper = $this->createMock(FormatterHelper::class); + $this->security = $this->createMock(CorePermissions::class); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->router = $this->createMock(UrlGeneratorInterface::class); + $this->translator = $this->createMock(Translator::class); + $this->userHelper = $this->createMock(UserHelper::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->coreParametersHelper = $this->createMock(CoreParametersHelper::class); + + $this->dateHelper = new DateHelper( + 'F j, Y g:i a T', + 'D, M d', + 'F j, Y', + 'g:i a', + $this->translator, + $this->coreParametersHelper, + ); + + $this->formatterHelper = new FormatterHelper( + $this->dateHelper, + $this->translator, + ); $this->filterOperatorProvider = $this->createMock(FilterOperatorProviderInterface::class); $this->customItemImportModel = new CustomItemImportModel( $this->entityManager, + $this->security, + $this->dispatcher, + $this->router, + $this->translator, + $this->userHelper, + $this->logger, + $this->coreParametersHelper, $this->customItemModel, $this->formatterHelper ); - /** @var TranslatorInterface $translator */ - $translator = $this->createMock(TranslatorInterface::class); - - $textareaType = new TextareaType($translator, $this->filterOperatorProvider); - $dateTimeType = new DateTimeType($translator, $this->filterOperatorProvider); + $textareaType = new TextareaType($this->translator, $this->filterOperatorProvider); + $dateTimeType = new DateTimeType($this->translator, $this->filterOperatorProvider); $this->descriptionField->method('getId')->willReturn(33); $this->descriptionField->method('getTypeObject')->willReturn($textareaType); $this->dateField->method('getId')->willReturn(34); $this->dateField->method('getTypeObject')->willReturn($dateTimeType); + + if (!method_exists(LeadRepository::class, 'exists')) { + $this->markTestSkipped(); + } } public function testImportForCreated(): void @@ -121,11 +193,6 @@ public function testImportForCreated(): void $this->customItemModel->expects($this->never()) ->method('fetchEntity'); - $this->formatterHelper->expects($this->once()) - ->method('simpleCsvToArray') - ->with('3262739,3262738,3262737') - ->willReturn([3262739, 3262738, 3262737]); - $this->customObject->expects($this->exactly(3)) ->method('getCustomFields') ->willReturn(new ArrayCollection([$this->descriptionField, $this->dateField])); @@ -149,6 +216,12 @@ public function testImportForCreated(): void })) ->willReturn($customItem); + $leadRepository = $this->createMock(LeadRepository::class); + $this->entityManager->expects($this->any()) + ->method('getRepository') + ->with(Lead::class) + ->willReturn($leadRepository); + $this->assertSame( false, $this->customItemImportModel->import($this->import, self::ROW_DATA, $this->customObject) @@ -161,11 +234,6 @@ public function testImportForCreatedWhenObjectHasNoFields(): void ->method('getMatchedFields') ->willReturn(self::MAPPED_FIELDS); - $this->formatterHelper->expects($this->once()) - ->method('simpleCsvToArray') - ->with('3262739,3262738,3262737') - ->willReturn([3262739, 3262738, 3262737]); - $this->customObject->expects($this->exactly(1)) ->method('getCustomFields') ->willReturn([]); @@ -218,11 +286,6 @@ public function testImportForUpdatedWithSetOwner(): void ->with(User::class, 222) ->willReturn(222); - $this->formatterHelper->expects($this->once()) - ->method('simpleCsvToArray') - ->with('3262739,3262738,3262737') - ->willReturn([3262739, 3262738, 3262737]); - $this->customItemModel->expects($this->exactly(3)) ->method('linkEntity') ->withConsecutive( @@ -236,6 +299,16 @@ public function testImportForUpdatedWithSetOwner(): void ->with($customItem) ->willReturn($customItem); + $leadRepository = $this->createMock(LeadRepository::class); + $leadRepository->expects($this->atLeast(3)) + ->method('exists') + ->willReturn(true); + + $this->entityManager->expects($this->any()) + ->method('getRepository') + ->with(Lead::class) + ->willReturn($leadRepository); + $this->customItemImportModel->import($this->import, $rowData, $this->customObject); } @@ -247,6 +320,53 @@ public function testImportForUpdatedWhenItemNotFound(): void $rowData['id'] = '555'; $customItem = $this->createMock(CustomItem::class); + $this->import->expects($this->exactly(2)) + ->method('getMatchedFields') + ->willReturn($mappedFields); + + $this->customObject->expects($this->exactly(3)) + ->method('getCustomFields') + ->willReturn(new ArrayCollection([$this->descriptionField, $this->dateField])); + + $this->customItemModel->expects($this->once()) + ->method('fetchEntity') + ->with(555) + ->will($this->throwException(new NotFoundException())); + + $this->customItemModel->expects($this->exactly(3)) + ->method('linkEntity') + ->withConsecutive( + [$customItem, 'contact', 3262739], + [$customItem, 'contact', 3262738], + [$customItem, 'contact', 3262737] + ); + + $this->customItemModel->expects($this->once()) + ->method('save') + ->with($this->isInstanceOf(CustomItem::class)) + ->willReturn($customItem); + + $leadRepository = $this->createMock(LeadRepository::class); + $leadRepository->expects($this->atLeast(3)) + ->method('exists') + ->willReturn(true); + + $this->entityManager->expects($this->any()) + ->method('getRepository') + ->with(Lead::class) + ->willReturn($leadRepository); + + $this->customItemImportModel->import($this->import, $rowData, $this->customObject); + } + + public function testImportWithLinkContactWhenGivenContactIdIsInvalid(): void + { + $mappedFields = self::MAPPED_FIELDS; + $rowData = self::ROW_DATA; + $mappedFields['id'] = 'customItemId'; + $rowData['id'] = '555'; + $customItem = $this->createMock(CustomItem::class); + $this->import->expects($this->exactly(2)) ->method('getMatchedFields') ->willReturn($mappedFields); @@ -265,7 +385,7 @@ public function testImportForUpdatedWhenItemNotFound(): void ->with('3262739,3262738,3262737') ->willReturn([3262739, 3262738, 3262737]); - $this->customItemModel->expects($this->exactly(3)) + $this->customItemModel->expects($this->exactly(1)) ->method('linkEntity') ->withConsecutive( [$customItem, 'contact', 3262739], @@ -278,6 +398,26 @@ public function testImportForUpdatedWhenItemNotFound(): void ->with($this->isInstanceOf(CustomItem::class)) ->willReturn($customItem); - $this->customItemImportModel->import($this->import, $rowData, $this->customObject); + $leadRepository = $this->createMock(LeadRepository::class); + $leadRepository->expects($this->atLeast(3)) + ->method('exists') + ->willReturnOnConsecutiveCalls(true, false, false); + + $this->entityManager->expects($this->any()) + ->method('getRepository') + ->with(Lead::class) + ->willReturn($leadRepository); + + $translator = $this->createMock(TranslatorInterface::class); + $translator->expects($this->any()) + ->method('trans') + ->willReturn('test warning'); + + $this->customItemImportModel->setTranslator($translator); + + $importLogDto = new ImportLogDTO(); + $this->customItemImportModel->import($this->import, $rowData, $this->customObject, $importLogDto); + + $this->assertTrue($importLogDto->hasWarning()); } } diff --git a/Tests/Unit/Model/CustomItemModelTest.php b/Tests/Unit/Model/CustomItemModelTest.php index fe8d9887f..bb01109c5 100644 --- a/Tests/Unit/Model/CustomItemModelTest.php +++ b/Tests/Unit/Model/CustomItemModelTest.php @@ -7,12 +7,16 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Query\QueryBuilder as DbalQueryBuilder; +use Doctrine\DBAL\Result; use Doctrine\DBAL\Statement; use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; +use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Helper\UserHelper; +use Mautic\CoreBundle\Security\Permissions\CorePermissions; +use Mautic\CoreBundle\Translation\Translator; use Mautic\UserBundle\Entity\User; use MauticPlugin\CustomObjectsBundle\CustomItemEvents; use MauticPlugin\CustomObjectsBundle\DTO\TableConfig; @@ -29,11 +33,13 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomItemModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomItemPermissionProvider; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Validator\ConstraintViolationListInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; -use UnexpectedValueException; class CustomItemModelTest extends TestCase { @@ -72,15 +78,44 @@ class CustomItemModelTest extends TestCase */ private $customItemModel; + /** + * @var CorePermissions|MockObject + */ + private $security; + + /** + * @var UrlGeneratorInterface|MockObject + */ + private $router; + + /** + * @var Translator|MockObject + */ + private $translator; + + /** + * @var LoggerInterface|MockObject + */ + private $logger; + + /** + * @var CoreParametersHelper|MockObject + */ + private $coreParametersHelper; + protected function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', getenv('MAUTIC_DB_PREFIX') ?: ''); - $this->customItem = $this->createMock(CustomItem::class); $this->user = $this->createMock(User::class); $this->entityManager = $this->createMock(EntityManager::class); + $this->security = $this->createMock(CorePermissions::class); + $this->router = $this->createMock(UrlGeneratorInterface::class); + $this->translator = $this->createMock(Translator::class); + $this->userHelper = $this->createMock(UserHelper::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->coreParametersHelper = $this->createMock(CoreParametersHelper::class); $this->queryBuilder = $this->createMock(QueryBuilder::class); $this->dbalQueryBuilder = $this->createMock(DbalQueryBuilder::class); $this->statement = $this->createMock(Statement::class); @@ -95,11 +130,16 @@ protected function setUp(): void $this->violationList = $this->createMock(ConstraintViolationListInterface::class); $this->customItemModel = new CustomItemModel( $this->entityManager, + $this->security, + $this->dispatcher, + $this->router, + $this->translator, + $this->userHelper, + $this->logger, + $this->coreParametersHelper, $this->customItemRepository, $this->customItemPermissionProvider, - $this->userHelper, $this->customFieldValueModel, - $this->dispatcher, $this->validator ); @@ -127,13 +167,13 @@ public function testSaveNew(): void $this->customItem->expects($this->never())->method('recordCustomFieldValueChanges'); $this->dispatcher->method('dispatch') ->withConsecutive( - [CustomItemEvents::ON_CUSTOM_ITEM_PRE_SAVE, $this->isInstanceOf(CustomItemEvent::class)], - [CustomItemEvents::ON_CUSTOM_ITEM_POST_SAVE, $this->isInstanceOf(CustomItemEvent::class)] + [$this->isInstanceOf(CustomItemEvent::class), CustomItemEvents::ON_CUSTOM_ITEM_PRE_SAVE], + [$this->isInstanceOf(CustomItemEvent::class), CustomItemEvents::ON_CUSTOM_ITEM_POST_SAVE] ); $this->customItemRepository->expects($this->once())->method('upsert')->with($this->customItem); $this->validator->expects($this->once())->method('validate')->with($this->customItem)->willReturn($this->violationList); - $this->expectException(NotFoundException::class); //since the fetchEntity() method is called on save and there's no customItem in the DB with ID 1 + $this->expectException(NotFoundException::class); // since the fetchEntity() method is called on save and there's no customItem in the DB with ID 1 $this->assertSame($this->customItem, $this->customItemModel->save($this->customItem)); } @@ -151,8 +191,8 @@ public function testSaveEdit(): void $this->customFieldValueModel->expects($this->once())->method('save')->with($customFieldValue); $this->dispatcher->method('dispatch') ->withConsecutive( - [CustomItemEvents::ON_CUSTOM_ITEM_PRE_SAVE, $this->isInstanceOf(CustomItemEvent::class)], - [CustomItemEvents::ON_CUSTOM_ITEM_POST_SAVE, $this->isInstanceOf(CustomItemEvent::class)] + [$this->isInstanceOf(CustomItemEvent::class), CustomItemEvents::ON_CUSTOM_ITEM_PRE_SAVE], + [$this->isInstanceOf(CustomItemEvent::class), CustomItemEvents::ON_CUSTOM_ITEM_POST_SAVE] ); $this->validator->expects($this->once())->method('validate')->with($this->customItem)->willReturn($this->violationList); @@ -164,8 +204,8 @@ public function testDelete(): void $this->customItem->expects($this->once())->method('getId')->willReturn(34); $this->dispatcher->method('dispatch') ->withConsecutive( - [CustomItemEvents::ON_CUSTOM_ITEM_PRE_DELETE, $this->isInstanceOf(CustomItemEvent::class)], - [CustomItemEvents::ON_CUSTOM_ITEM_POST_DELETE, $this->isInstanceOf(CustomItemEvent::class)] + [$this->isInstanceOf(CustomItemEvent::class), CustomItemEvents::ON_CUSTOM_ITEM_PRE_DELETE], + [$this->isInstanceOf(CustomItemEvent::class), CustomItemEvents::ON_CUSTOM_ITEM_POST_DELETE] ); $this->entityManager->expects($this->once())->method('remove')->with($this->customItem); $this->entityManager->expects($this->once())->method('flush'); @@ -178,17 +218,17 @@ public function testLinkEntityIfXrefNotFound(): void $this->dispatcher->expects($this->once()) ->method('dispatch') ->with( - CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY, $this->callback(function (CustomItemXrefEntityDiscoveryEvent $event) { $this->assertSame($this->customItem, $event->getCustomItem()); $this->assertSame('contact', $event->getEntityType()); $this->assertSame(123, $event->getEntityId()); return true; - }) + }), + CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY ); - $this->expectException(UnexpectedValueException::class); + $this->expectException(\UnexpectedValueException::class); $this->customItemModel->linkEntity($this->customItem, 'contact', 123); } @@ -200,7 +240,6 @@ public function testLinkEntity(): void ->method('dispatch') ->withConsecutive( [ - CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY, $this->callback(function (CustomItemXrefEntityDiscoveryEvent $event) use ($xref) { $this->assertSame($this->customItem, $event->getCustomItem()); $this->assertSame('contact', $event->getEntityType()); @@ -211,14 +250,15 @@ public function testLinkEntity(): void return true; }), + CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY, ], [ - CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY, $this->callback(function (CustomItemXrefEntityEvent $event) use ($xref) { $this->assertSame($xref, $event->getXref()); return true; }), + CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY, ] ); @@ -230,17 +270,17 @@ public function testUninkEntityIfXrefNotFound(): void $this->dispatcher->expects($this->once()) ->method('dispatch') ->with( - CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY, $this->callback(function (CustomItemXrefEntityDiscoveryEvent $event) { $this->assertSame($this->customItem, $event->getCustomItem()); $this->assertSame('contact', $event->getEntityType()); $this->assertSame(123, $event->getEntityId()); return true; - }) + }), + CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY ); - $this->expectException(UnexpectedValueException::class); + $this->expectException(\UnexpectedValueException::class); $this->customItemModel->unlinkEntity($this->customItem, 'contact', 123); } @@ -252,7 +292,6 @@ public function testUninkEntity(): void ->method('dispatch') ->withConsecutive( [ - CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY, $this->callback(function (CustomItemXrefEntityDiscoveryEvent $event) use ($xref) { $this->assertSame($this->customItem, $event->getCustomItem()); $this->assertSame('contact', $event->getEntityType()); @@ -263,14 +302,15 @@ public function testUninkEntity(): void return true; }), + CustomItemEvents::ON_CUSTOM_ITEM_LINK_ENTITY_DISCOVERY, ], [ - CustomItemEvents::ON_CUSTOM_ITEM_UNLINK_ENTITY, $this->callback(function (CustomItemXrefEntityEvent $event) use ($xref) { $this->assertSame($xref, $event->getXref()); return true; }), + CustomItemEvents::ON_CUSTOM_ITEM_UNLINK_ENTITY, ] ); @@ -314,7 +354,7 @@ public function testGetTableDataWithoutCustomObjectId(): void { $tableConfig = new TableConfig(10, 1, 'column'); - $this->expectException(UnexpectedValueException::class); + $this->expectException(\UnexpectedValueException::class); $this->expectExceptionMessage("customObjectId cannot be empty. It's required for permission management"); $this->customItemModel->getTableData($tableConfig); } @@ -341,8 +381,7 @@ public function testGetTableData(): void ->willReturn([]); $this->dispatcher->expects($this->once()) - ->method('dispatch') - ->with(CustomItemEvents::ON_CUSTOM_ITEM_LIST_ORM_QUERY); + ->method('dispatch'); $this->customItemModel->getTableData($tableConfig); } @@ -351,7 +390,7 @@ public function testGetArrayTableDataWithoutCustomObjectId(): void { $tableConfig = new TableConfig(10, 1, 'column'); - $this->expectException(UnexpectedValueException::class); + $this->expectException(\UnexpectedValueException::class); $this->expectExceptionMessage("customObjectId cannot be empty. It's required for permission management"); $this->customItemModel->getArrayTableData($tableConfig); } @@ -373,21 +412,22 @@ public function testGetArrayTableData(): void ->method('select') ->willReturn(CustomItem::TABLE_ALIAS.'.*'); + $result = $this->createMock(Result::class); + + $result->expects($this->once()) + ->method('fetchAllAssociative') + ->willReturn([]); + $this->dbalQueryBuilder->expects($this->once()) ->method('execute') - ->willReturn($this->statement); + ->willReturn($result); $this->dbalQueryBuilder->expects($this->once()) ->method('setParameter') ->with('customObjectId', 44); - $this->statement->expects($this->once()) - ->method('fetchAll') - ->willReturn([]); - $this->dispatcher->expects($this->once()) - ->method('dispatch') - ->with(CustomItemEvents::ON_CUSTOM_ITEM_LIST_DBAL_QUERY); + ->method('dispatch'); $this->customItemModel->getArrayTableData($tableConfig); } diff --git a/Tests/Unit/Model/CustomItemXrefContactModelTest.php b/Tests/Unit/Model/CustomItemXrefContactModelTest.php index 0160aa3a7..f8102deb4 100644 --- a/Tests/Unit/Model/CustomItemXrefContactModelTest.php +++ b/Tests/Unit/Model/CustomItemXrefContactModelTest.php @@ -4,16 +4,21 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Model; -use DateTime; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Query\QueryBuilder as DBALQueryBuilder; use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\EntityManager; use Doctrine\ORM\QueryBuilder; +use Mautic\CoreBundle\Helper\CoreParametersHelper; +use Mautic\CoreBundle\Helper\UserHelper; +use Mautic\CoreBundle\Security\Permissions\CorePermissions; +use Mautic\CoreBundle\Translation\Translator; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Model\CustomItemXrefContactModel; -use Symfony\Component\Translation\TranslatorInterface; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class CustomItemXrefContactModelTest extends \PHPUnit\Framework\TestCase { @@ -21,12 +26,45 @@ class CustomItemXrefContactModelTest extends \PHPUnit\Framework\TestCase private $entityManager; - private $queryBuilder; + /** + * @var MockObject|CorePermissions + */ + private $security; - private $query; + /** + * @var MockObject|EventDispatcherInterface + */ + private $dispatcher; + + /** + * @var MockObject|UrlGeneratorInterface + */ + private $router; + /** + * @var MockObject|Translator + */ private $translator; + /** + * @var MockObject|UserHelper + */ + private $userHelper; + + /** + * @var MockObject|LoggerInterface + */ + private $logger; + + /** + * @var MockObject|CoreParametersHelper + */ + private $coreParametersHelper; + + private $queryBuilder; + + private $query; + /** * @var CustomItemXrefContactModel */ @@ -40,10 +78,22 @@ protected function setUp(): void $this->entityManager = $this->createMock(EntityManager::class); $this->queryBuilder = $this->createMock(QueryBuilder::class); $this->query = $this->createMock(AbstractQuery::class); - $this->translator = $this->createMock(TranslatorInterface::class); + $this->translator = $this->createMock(Translator::class); + $this->security = $this->createMock(CorePermissions::class); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->router = $this->createMock(UrlGeneratorInterface::class); + $this->userHelper = $this->createMock(UserHelper::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->coreParametersHelper = $this->createMock(CoreParametersHelper::class); $this->customItemXrefContactModel = new CustomItemXrefContactModel( $this->entityManager, - $this->translator + $this->security, + $this->dispatcher, + $this->router, + $this->translator, + $this->userHelper, + $this->logger, + $this->coreParametersHelper, ); $this->entityManager->method('createQueryBuilder')->willReturn($this->queryBuilder); @@ -52,13 +102,10 @@ protected function setUp(): void public function testGetLinksLineChartData(): void { - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); - - $from = new DateTime('2019-03-02 12:30:00'); - $to = new DateTime('2019-04-02 12:30:00'); + $from = new \DateTime('2019-03-02 12:30:00'); + $to = new \DateTime('2019-04-02 12:30:00'); $connection = $this->createMock(Connection::class); $queryBuilder = $this->createMock(DBALQueryBuilder::class); - $statement = $this->createMock(Statement::class); $this->entityManager->expects($this->once()) ->method('getConnection') @@ -68,14 +115,6 @@ public function testGetLinksLineChartData(): void ->method('createQueryBuilder') ->willReturn($queryBuilder); - $queryBuilder->expects($this->once()) - ->method('execute') - ->willReturn($statement); - - $statement->expects($this->once()) - ->method('fetchAll') - ->willReturn([]); - $chartData = $this->customItemXrefContactModel->getLinksLineChartData( $from, $to, diff --git a/Tests/Unit/Model/CustomObjectModelTest.php b/Tests/Unit/Model/CustomObjectModelTest.php index 9ebc2cdeb..331e1da66 100644 --- a/Tests/Unit/Model/CustomObjectModelTest.php +++ b/Tests/Unit/Model/CustomObjectModelTest.php @@ -6,14 +6,17 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Platforms\MySqlPlatform; +use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; use Doctrine\DBAL\Query\QueryBuilder as QueryBuilderDbal; use Doctrine\DBAL\Statement; use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; +use Mautic\CoreBundle\Helper\CoreParametersHelper; use Mautic\CoreBundle\Helper\UserHelper; +use Mautic\CoreBundle\Security\Permissions\CorePermissions; +use Mautic\CoreBundle\Translation\Translator; use Mautic\LeadBundle\Model\ListModel; use Mautic\UserBundle\Entity\User; use MauticPlugin\CustomObjectsBundle\CustomObjectEvents; @@ -27,9 +30,11 @@ use MauticPlugin\CustomObjectsBundle\Model\CustomObjectModel; use MauticPlugin\CustomObjectsBundle\Provider\CustomObjectPermissionProvider; use MauticPlugin\CustomObjectsBundle\Repository\CustomObjectRepository; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class CustomObjectModelTest extends TestCase { @@ -37,6 +42,41 @@ class CustomObjectModelTest extends TestCase private $customField; private $user; private $entityManager; + + /** + * @var MockObject|CorePermissions + */ + private $security; + + /** + * @var MockObject|EventDispatcherInterface + */ + private $dispatcher; + + /** + * @var MockObject|UrlGeneratorInterface + */ + private $router; + + /** + * @var MockObject|Translator + */ + private $translator; + + /** + * @var MockObject|UserHelper + */ + private $userHelper; + + /** + * @var MockObject|LoggerInterface + */ + private $logger; + + /** + * @var MockObject|CoreParametersHelper + */ + private $coreParametersHelper; private $queryBuilder; private $queryBuilderDbal; private $query; @@ -45,10 +85,7 @@ class CustomObjectModelTest extends TestCase private $databasePlatform; private $customObjectRepository; private $customObjectPermissionProvider; - private $userHelper; private $customFieldModel; - private $dispatcher; - private $translator; /** * @var ListModel @@ -64,37 +101,41 @@ protected function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); - $this->customObject = $this->createMock(CustomObject::class); $this->customField = $this->createMock(CustomField::class); $this->user = $this->createMock(User::class); $this->entityManager = $this->createMock(EntityManager::class); + $this->translator = $this->createMock(Translator::class); + $this->security = $this->createMock(CorePermissions::class); + $this->dispatcher = $this->createMock(EventDispatcherInterface::class); + $this->router = $this->createMock(UrlGeneratorInterface::class); + $this->userHelper = $this->createMock(UserHelper::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->coreParametersHelper = $this->createMock(CoreParametersHelper::class); $this->queryBuilder = $this->createMock(QueryBuilder::class); $this->queryBuilderDbal = $this->createMock(QueryBuilderDbal::class); $this->statement = $this->createMock(Statement::class); $this->query = $this->createMock(AbstractQuery::class); $this->connection = $this->createMock(Connection::class); - $this->databasePlatform = $this->createMock(MySqlPlatform::class); + $this->databasePlatform = $this->createMock(AbstractMySQLPlatform::class); $this->customObjectRepository = $this->createMock(CustomObjectRepository::class); $this->customObjectPermissionProvider = $this->createMock(CustomObjectPermissionProvider::class); - $this->userHelper = $this->createMock(UserHelper::class); $this->customFieldModel = $this->createMock(CustomFieldModel::class); - $this->dispatcher = $this->createMock(EventDispatcherInterface::class); - $this->translator = $this->createMock(TranslatorInterface::class); $this->listModel = $this->createMock(ListModel::class); $this->customObjectModel = new CustomObjectModel( $this->entityManager, + $this->security, + $this->dispatcher, + $this->router, + $this->translator, + $this->userHelper, + $this->logger, + $this->coreParametersHelper, $this->customObjectRepository, $this->customObjectPermissionProvider, - $this->userHelper, $this->customFieldModel, - $this->dispatcher, - $this->listModel ); - $this->customObjectModel->setEntityManager($this->entityManager); - $this->customObjectModel->setTranslator($this->translator); $this->entityManager->method('createQueryBuilder')->willReturn($this->queryBuilder); $this->entityManager->method('getConnection')->willReturn($this->connection); $this->connection->method('getDatabasePlatform')->willReturn($this->databasePlatform); @@ -161,8 +202,8 @@ public function testSaveNew(): void $this->dispatcher->method('dispatch') ->withConsecutive( - [CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_SAVE, $this->isInstanceOf(CustomObjectEvent::class)], - [CustomObjectEvents::ON_CUSTOM_OBJECT_POST_SAVE, $this->isInstanceOf(CustomObjectEvent::class)] + [$this->isInstanceOf(CustomObjectEvent::class), CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_SAVE], + [$this->isInstanceOf(CustomObjectEvent::class), CustomObjectEvents::ON_CUSTOM_OBJECT_POST_SAVE] ); $this->entityManager->expects($this->once())->method('persist')->with($this->customObject); $this->entityManager->expects($this->once())->method('flush'); @@ -241,8 +282,8 @@ public function testSaveNewWhenAliasIsNotUnique(): void $this->dispatcher->method('dispatch') ->withConsecutive( - [CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_SAVE, $this->isInstanceOf(CustomObjectEvent::class)], - [CustomObjectEvents::ON_CUSTOM_OBJECT_POST_SAVE, $this->isInstanceOf(CustomObjectEvent::class)] + [$this->isInstanceOf(CustomObjectEvent::class), CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_SAVE], + [$this->isInstanceOf(CustomObjectEvent::class), CustomObjectEvents::ON_CUSTOM_OBJECT_POST_SAVE] ); $this->entityManager->expects($this->once())->method('persist')->with($this->customObject); $this->entityManager->expects($this->once())->method('flush'); @@ -294,8 +335,8 @@ public function testSaveEdit(): void $this->dispatcher->method('dispatch') ->withConsecutive( - [CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_SAVE, $this->isInstanceOf(CustomObjectEvent::class)], - [CustomObjectEvents::ON_CUSTOM_OBJECT_POST_SAVE, $this->isInstanceOf(CustomObjectEvent::class)] + [$this->isInstanceOf(CustomObjectEvent::class), CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_SAVE], + [$this->isInstanceOf(CustomObjectEvent::class), CustomObjectEvents::ON_CUSTOM_OBJECT_POST_SAVE] ); $this->entityManager->expects($this->once())->method('persist')->with($this->customObject); $this->entityManager->expects($this->once())->method('flush'); @@ -311,7 +352,7 @@ public function testDelete(): void $this->dispatcher->method('dispatch') ->withConsecutive( - [CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_DELETE, $this->isInstanceOf(CustomObjectEvent::class)] + [$this->isInstanceOf(CustomObjectEvent::class), CustomObjectEvents::ON_CUSTOM_OBJECT_PRE_DELETE] ); $this->entityManager->expects($this->once()) @@ -577,10 +618,6 @@ public function testGetItemsLineChartData(): void ->with('custom.object.created.items') ->willReturn('Items Created'); - $this->statement->expects($this->once()) - ->method('fetchAll') - ->willReturn([]); - $chartData = $this->customObjectModel->getItemsLineChartData( $from, $to, diff --git a/Tests/Unit/Provider/CustomFieldTypeProviderTest.php b/Tests/Unit/Provider/CustomFieldTypeProviderTest.php index 31f126a1f..14f4dd578 100644 --- a/Tests/Unit/Provider/CustomFieldTypeProviderTest.php +++ b/Tests/Unit/Provider/CustomFieldTypeProviderTest.php @@ -11,7 +11,7 @@ use MauticPlugin\CustomObjectsBundle\CustomFieldType\TextType; use MauticPlugin\CustomObjectsBundle\Exception\NotFoundException; use MauticPlugin\CustomObjectsBundle\Provider\CustomFieldTypeProvider; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomFieldTypeProviderTest extends \PHPUnit\Framework\TestCase { diff --git a/Tests/Unit/Report/ReportColumnsBuilderTest.php b/Tests/Unit/Report/ReportColumnsBuilderTest.php index eb34c1167..05c2822c7 100644 --- a/Tests/Unit/Report/ReportColumnsBuilderTest.php +++ b/Tests/Unit/Report/ReportColumnsBuilderTest.php @@ -17,7 +17,7 @@ use MauticPlugin\CustomObjectsBundle\Report\ReportColumnsBuilder; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class ReportColumnsBuilderTest extends TestCase { @@ -58,8 +58,6 @@ class ReportColumnsBuilderTest extends TestCase protected function setUp(): void { - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', getenv('MAUTIC_DB_PREFIX') ?: ''); - $this->customObject = $this->createMock(CustomObject::class); $this->reportColumnsBuilder = new ReportColumnsBuilder($this->customObject); $this->connection = $this->createMock(Connection::class); diff --git a/Tests/Unit/Repository/CustomFieldRepositoryTest.php b/Tests/Unit/Repository/CustomFieldRepositoryTest.php index 8746c0b85..af91594b8 100644 --- a/Tests/Unit/Repository/CustomFieldRepositoryTest.php +++ b/Tests/Unit/Repository/CustomFieldRepositoryTest.php @@ -5,21 +5,32 @@ namespace MauticPlugin\CustomObjectsBundle\Tests\Unit\Repository; use Doctrine\ORM\AbstractQuery; -use Doctrine\ORM\EntityManager; +use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; +use Doctrine\Persistence\ManagerRegistry; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Repository\CustomFieldRepository; +use PHPUnit\Framework\MockObject\MockObject; class CustomFieldRepositoryTest extends \PHPUnit\Framework\TestCase { private $entityManager; - private $classMetadata; private $queryBuilder; private $query; private $expression; + /** + * @var MockObject|ClassMetadata + */ + private $classMetadata; + + /** + * @var MockObject|ManagerRegistry + */ + private $registry; + /** * @var CustomFieldRepository */ @@ -29,16 +40,18 @@ protected function setUp(): void { parent::setUp(); - $this->entityManager = $this->createMock(EntityManager::class); + $this->registry = $this->createMock(ManagerRegistry::class); + $this->entityManager = $this->createMock(EntityManagerInterface::class); $this->classMetadata = $this->createMock(ClassMetadata::class); $this->queryBuilder = $this->createMock(QueryBuilder::class); $this->query = $this->createMock(AbstractQuery::class); $this->expression = $this->createMock(Expr::class); $this->repository = new CustomFieldRepository( - $this->entityManager, - $this->classMetadata + $this->registry, ); + $this->registry->method('getManagerForClass')->willReturn($this->entityManager); + $this->entityManager->method('getClassMetadata')->willReturn($this->classMetadata); $this->entityManager->method('createQueryBuilder')->willReturn($this->queryBuilder); $this->queryBuilder->method('getQuery')->willReturn($this->query); $this->queryBuilder->method('expr')->willReturn($this->expression); diff --git a/Tests/Unit/Repository/CustomItemRepositoryTest.php b/Tests/Unit/Repository/CustomItemRepositoryTest.php index 5c2430bdd..d4dedbc9b 100644 --- a/Tests/Unit/Repository/CustomItemRepositoryTest.php +++ b/Tests/Unit/Repository/CustomItemRepositoryTest.php @@ -9,6 +9,7 @@ use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; +use Doctrine\Persistence\ManagerRegistry; use Mautic\LeadBundle\Entity\Lead; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefContact; @@ -16,6 +17,7 @@ use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemRepository; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; class CustomItemRepositoryTest extends TestCase @@ -32,12 +34,15 @@ class CustomItemRepositoryTest extends TestCase */ private $customItemRepository; + /** + * @var MockObject|ManagerRegistry + */ + private $registry; + protected function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); - $this->entityManager = $this->createMock(EntityManager::class); $classMetadata = $this->createMock(ClassMetadata::class); $this->customObject = $this->createMock(CustomObject::class); @@ -45,10 +50,13 @@ protected function setUp(): void $this->queryBuilder = $this->createMock(QueryBuilder::class); $this->expr = $this->createMock(Expr::class); $this->query = $this->createMock(AbstractQuery::class); + $this->registry = $this->createMock(ManagerRegistry::class); $this->customItemRepository = new CustomItemRepository( - $this->entityManager, - $classMetadata + $this->registry, ); + + $this->registry->method('getManagerForClass')->willReturn($this->entityManager); + $this->entityManager->method('getClassMetadata')->willReturn($classMetadata); } public function testCountItemsLinkedToContact(): void diff --git a/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php b/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php index 85784b66e..ceb4d303e 100644 --- a/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php +++ b/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php @@ -13,12 +13,14 @@ use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; +use Doctrine\Persistence\ManagerRegistry; use Mautic\LeadBundle\Entity\Lead; use MauticPlugin\CustomObjectsBundle\DTO\TableConfig; use MauticPlugin\CustomObjectsBundle\Entity\CustomItem; use MauticPlugin\CustomObjectsBundle\Entity\CustomItemXrefContact; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Repository\CustomItemXrefContactRepository; +use PHPUnit\Framework\MockObject\MockObject; class CustomItemXrefContactRepositoryTest extends \PHPUnit\Framework\TestCase { @@ -38,12 +40,15 @@ class CustomItemXrefContactRepositoryTest extends \PHPUnit\Framework\TestCase */ private $repository; + /** + * @var MockObject|ManagerRegistry + */ + private $registry; + protected function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); - $this->entityManager = $this->createMock(EntityManager::class); $this->classMetadata = $this->createMock(ClassMetadata::class); $this->contact = $this->createMock(Lead::class); @@ -54,11 +59,13 @@ protected function setUp(): void $this->expr = $this->createMock(Expr::class); $this->expressionBuilder = $this->createMock(ExpressionBuilder::class); $this->query = $this->createMock(AbstractQuery::class); + $this->registry = $this->createMock(ManagerRegistry::class); $this->repository = new CustomItemXrefContactRepository( - $this->entityManager, - $this->classMetadata + $this->registry, ); + $this->registry->method('getManagerForClass')->willReturn($this->entityManager); + $this->entityManager->method('getClassMetadata')->willReturn($this->classMetadata); $this->entityManager->method('createQueryBuilder')->willReturn($this->queryBuilder); $this->entityManager->method('getConnection')->willReturn($this->connection); $this->connection->method('createQueryBuilder')->willReturn($this->queryBuilderDbal); diff --git a/Tests/Unit/Repository/CustomObjectRepositoryTest.php b/Tests/Unit/Repository/CustomObjectRepositoryTest.php index 20f60c82b..d522892c0 100644 --- a/Tests/Unit/Repository/CustomObjectRepositoryTest.php +++ b/Tests/Unit/Repository/CustomObjectRepositoryTest.php @@ -10,6 +10,7 @@ use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\QueryBuilder; +use Doctrine\Persistence\ManagerRegistry; use MauticPlugin\CustomObjectsBundle\Entity\CustomField; use MauticPlugin\CustomObjectsBundle\Entity\CustomObject; use MauticPlugin\CustomObjectsBundle\Repository\CustomObjectRepository; @@ -48,6 +49,11 @@ class CustomObjectRepositoryTest extends TestCase */ private $repository; + /** + * @var MockObject|ManagerRegistry + */ + private $registry; + protected function setUp(): void { parent::setUp(); @@ -57,11 +63,13 @@ protected function setUp(): void $this->queryBuilder = $this->createMock(QueryBuilder::class); $this->query = $this->createMock(AbstractQuery::class); $this->expression = $this->createMock(Expr::class); + $this->registry = $this->createMock(ManagerRegistry::class); $this->repository = new CustomObjectRepository( - $this->entityManager, - $this->classMetadata + $this->registry, ); + $this->registry->method('getManagerForClass')->willReturn($this->entityManager); + $this->entityManager->method('getClassMetadata')->willReturn($this->classMetadata); $this->entityManager->method('createQueryBuilder')->willReturn($this->queryBuilder); $this->queryBuilder->method('getQuery')->willReturn($this->query); $this->queryBuilder->method('expr')->willReturn($this->expression); diff --git a/Tests/Unit/Security/Permissions/CustomObjectPermissionsTest.php b/Tests/Unit/Security/Permissions/CustomObjectPermissionsTest.php index 13f8cb88e..a63cd0841 100644 --- a/Tests/Unit/Security/Permissions/CustomObjectPermissionsTest.php +++ b/Tests/Unit/Security/Permissions/CustomObjectPermissionsTest.php @@ -12,7 +12,7 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; class CustomObjectPermissionsTest extends TestCase { diff --git a/Tests/Unit/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php b/Tests/Unit/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php index 663ea1547..6d479bbae 100644 --- a/Tests/Unit/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php +++ b/Tests/Unit/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php @@ -50,7 +50,6 @@ class CustomItemNameFilterQueryBuilderTest extends TestCase protected function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); $randomParameter = new RandomParameterName(); $eventDispatcher = $this->createMock(EventDispatcherInterface::class); @@ -68,7 +67,8 @@ protected function setUp(): void $this->createMock(CustomFieldRepository::class), new QueryFilterFactory\Calculator(), 1 - ) + ), + new RandomParameterName() ); $this->queryBuilder = $this->createMock(QueryBuilder::class); @@ -90,8 +90,6 @@ public function testGetServiceId(): void /** * @dataProvider parameterValueProvider - * - * @param $parameterValue */ public function testApplyQuery($parameterValue): void { diff --git a/Tests/Unit/Segment/Query/Filter/QueryFilterFactoryTest.php b/Tests/Unit/Segment/Query/Filter/QueryFilterFactoryTest.php index 8ea086251..622b0dc9d 100644 --- a/Tests/Unit/Segment/Query/Filter/QueryFilterFactoryTest.php +++ b/Tests/Unit/Segment/Query/Filter/QueryFilterFactoryTest.php @@ -52,8 +52,6 @@ protected function setUp(): void { parent::setUp(); - defined('MAUTIC_TABLE_PREFIX') || define('MAUTIC_TABLE_PREFIX', ''); - $this->contactSegmentFilterFactory = $this->createMock(ContactSegmentFilterFactory::class); $this->queryFilterHelper = $this->createMock(QueryFilterHelper::class); $this->contactSegmentFilter = $this->createMock(ContactSegmentFilter::class); diff --git a/Translations/en_US/messages.ini b/Translations/en_US/messages.ini index 5ea104d7f..646e1353a 100644 --- a/Translations/en_US/messages.ini +++ b/Translations/en_US/messages.ini @@ -99,3 +99,4 @@ mautic.report.group.custom.objects="Custom Objects" custom.item.export="Export As CSV" custom.item.export.email_subject="Custom Items Exported : %file_name%" custom.item.export.email="Your requested custom item export: %label%." +custom.item.import.invalid.contactid.for.link="warning: Invalid contact %contactId% to link with customItem %customItemId%" diff --git a/Views/CustomField/detail.html.php b/Views/CustomField/detail.html.php deleted file mode 100644 index c97b8ac83..000000000 --- a/Views/CustomField/detail.html.php +++ /dev/null @@ -1,56 +0,0 @@ -extend('MauticCoreBundle:Default:content.html.php'); -$view['slots']->set('mauticContent', 'customField'); -$view['slots']->set('headerTitle', $item->getName()); -$view['slots']->set('actions', $view->render('MauticCoreBundle:Helper:page_actions.html.php', [ - 'item' => $item, -])); -?> - - -
    - -
    -
    - -
    -
    -
    -
    getType(); ?>
    -
    -
    - render('MauticCoreBundle:Helper:publishstatus_badge.html.php', ['entity' => $item]); ?> -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    - - -
    - -
    -
    -
    trans('mautic.webhook.webhook_url');?>
    -
    -
    -
    -
    -
    - -
    - - - render('MauticCoreBundle:Helper:recentactivity.html.php', ['logs' => $logs]);?> -
    -
    - -
    diff --git a/Views/CustomField/form.html.php b/Views/CustomField/form.html.php deleted file mode 100644 index 1ca60993e..000000000 --- a/Views/CustomField/form.html.php +++ /dev/null @@ -1,105 +0,0 @@ -getId() ? $customField->getLabel() : $customField->getTypeObject()->getName(); - -$showProperties = isset($form['options']) || $customField->getTypeObject()->usePlaceholder(); -?> - -
    - -
    -

    -
    - - start($form); ?> - -
    - - - -
    -
    - -
    -
    - row($form['label']); ?> -
    -
    - row($form['showInCustomObjectDetailList']); ?> -
    -
    - -
    -
    - row($form['alias']); ?> -
    -
    - row($form['showInContactDetailList']); ?> -
    -
    - -
    -
    - row($form['defaultValue']); ?> -
    -
    - row($form['isUniqueIdentifier']); ?> -
    -
    - -
    - -
    -
    -
    - row($form['required']); ?> -
    -
    -
    - - -
    -
    - -
    - row($form['options']); ?> -
    - -
    -
    -getTypeObject()->usePlaceholder()): ?> -
    - row($form['params']['placeholder']); ?> -
    - -
    -
    - - -
    - -
    - - rest($form); ?> - end($form); ?> - -
    \ No newline at end of file diff --git a/Views/CustomField/index.html.php b/Views/CustomField/index.html.php deleted file mode 100644 index c1a0aaa20..000000000 --- a/Views/CustomField/index.html.php +++ /dev/null @@ -1,21 +0,0 @@ -extend('MauticCoreBundle:Default:content.html.php'); - -$view['slots']->set('mauticContent', 'customField'); -$view['slots']->set('headerTitle', $view['translator']->trans('custom.field.title')); -$view['slots']->set('actions', $view->render('MauticCoreBundle:Helper:page_actions.html.php')); -?> - -
    - render( - 'MauticCoreBundle:Helper:list_toolbar.html.php', - [ - // 'searchValue' => $searchValue, - // 'action' => $currentRoute, - ] -); ?> -
    - output('_content'); ?> -
    -
    diff --git a/Views/CustomField/value.html.php b/Views/CustomField/value.html.php deleted file mode 100644 index 35be77316..000000000 --- a/Views/CustomField/value.html.php +++ /dev/null @@ -1,23 +0,0 @@ -getCustomField()->getType(); -?> -getValue() instanceof DateTimeInterface) : ?> - - toDate($fieldValue->getValue()); ?> - - toFull($fieldValue->getValue()); ?> - - - escape($fieldValue->getCustomField()->getTypeObject()->valueToString($fieldValue)); ?> -getValue())) : ?> - escape($view['formatter']->arrayToString($fieldValue->getValue())); ?> - - escape($fieldValue->getValue()); ?> - \ No newline at end of file diff --git a/Views/CustomItem/detail.html.php b/Views/CustomItem/detail.html.php deleted file mode 100644 index 25b27e74e..000000000 --- a/Views/CustomItem/detail.html.php +++ /dev/null @@ -1,125 +0,0 @@ -extend('MauticCoreBundle:Default:content.html.php'); -$view['slots']->set('mauticContent', 'customItem'); -$view['slots']->set('headerTitle', $item->getName()); -$view['slots']->set('actions', $view->render('MauticCoreBundle:Helper:page_actions.html.php', [ - 'item' => $item, -])); -?> - - -
    - -
    -
    - -
    -
    -
    -
    escape($item->getCustomObject()->getNameSingular()); ?>
    -
    -
    - render('MauticCoreBundle:Helper:publishstatus_badge.html.php', ['entity' => $item]); ?> -
    -
    -
    - - -
    -
    -
    - - - render( - 'MauticCoreBundle:Helper:details.html.php', - ['entity' => $item] -); ?> - getCustomFieldValues() as $fieldValue) : ?> - - - - - - -
    escape($fieldValue->getCustomField()->getName()); ?> - render('CustomObjectsBundle:CustomField:value.html.php', ['fieldValue' => $fieldValue]); ?> -
    -
    -
    -
    -
    - - -
    - - - - -
    -
    -
    -
    -
    -
    -
    - - trans('custom.item.links.in.time'); ?> -
    -
    -
    - render( - 'MauticCoreBundle:Helper:graph_dateselect.html.php', - ['dateRangeForm' => $dateRangeForm, 'class' => 'pull-right'] -); ?> -
    -
    -
    - render( - 'MauticCoreBundle:Helper:chart.html.php', - ['chartData' => $stats, 'chartType' => 'line', 'chartHeight' => 300] -); ?> -
    -
    -
    -
    -
    - - getCustomContent('details.stats.graph.below', $mauticTemplateVars); ?> -
    - - - - - - -
    -
    - -
    - getCustomContent('tabs.content', $mauticTemplateVars); ?> -
    - -
    - - -
    - - render('MauticCoreBundle:Helper:recentactivity.html.php', ['logs' => $logs]); ?> -
    - -
    diff --git a/Views/CustomItem/form.html.php b/Views/CustomItem/form.html.php deleted file mode 100644 index c39a6f0b7..000000000 --- a/Views/CustomItem/form.html.php +++ /dev/null @@ -1,71 +0,0 @@ -extend('MauticCoreBundle:Default:content.html.php'); - -$view['slots']->set('mauticContent', 'customItem'); - -if ($entity->getId()) { - $header = $view['translator']->trans( - 'custom.item.edit', - [ - '%object%' => $view['translator']->trans($customObject->getNameSingular()), - '%item%' => $view['translator']->trans($entity->getName()), - ] - ); -} else { - $header = $view['translator']->trans( - 'custom.item.new', - ['%object%' => $view['translator']->trans($customObject->getNameSingular())] - ); -} - -$view['slots']->set('headerTitle', $header); - -$hideCategories = CustomObject::TYPE_RELATIONSHIP === $customObject->getType() ? 'hide' : null; -?> - -start($form); ?> - - -
    - -
    -
    -
    -
    - rowIfExists($form, 'name'); ?> - row($form['custom_field_values']); ?> - row($form['contact_id']); ?> -
    - getRelationshipObject() && !empty($form['contact_id']->vars['value'])) : ?> -
    -
    -
    -

    - trans( - 'custom.item.new', - ['%object%' => $view['translator']->trans($customObject->getRelationshipObject()->getNameSingular())] -); ?> -

    -
    -
    - rowIfExists($form, 'child_custom_field_values'); ?> -
    -
    -
    - -
    -
    -
    -
    -
    - row($form['category']); ?> - row($form['isPublished']); ?> -
    -
    -
    - -end($form); ?> diff --git a/Views/CustomItem/index.html.php b/Views/CustomItem/index.html.php deleted file mode 100644 index a8cf67cb5..000000000 --- a/Views/CustomItem/index.html.php +++ /dev/null @@ -1,27 +0,0 @@ -extend('MauticCoreBundle:Default:content.html.php'); - - $view['slots']->set('mauticContent', 'customItem'); - $view['slots']->set('headerTitle', $customObject->getName()); - $view['slots']->set('actions', $view->render('MauticCoreBundle:Helper:page_actions.html.php')); -} -?> - -
    -
    - render( - 'MauticCoreBundle:Helper:list_toolbar.html.php', - [ - 'searchValue' => $searchValue, - 'action' => $currentRoute, - 'target' => '#'.$namespace, - 'overlayDisabled' => $lookup, - ] -); ?> -
    - output('_content'); ?> -
    -
    -
    diff --git a/Views/CustomItem/list.html.php b/Views/CustomItem/list.html.php deleted file mode 100644 index 317d6deb4..000000000 --- a/Views/CustomItem/list.html.php +++ /dev/null @@ -1,124 +0,0 @@ -extend('CustomObjectsBundle:CustomItem:index.html.php'); -} - -$target = '#'.$namespace; -$routeSelf = $view['router']->path( - CustomItemRouteProvider::ROUTE_LIST, - [ - 'objectId' => $customObject->getId(), - 'filterEntityId' => $filterEntityId, - 'filterEntityType' => $filterEntityType, - 'lookup' => $lookup, - 'tmpl' => 'list', - ] -); -?> - -
    - - - - render( - 'MauticCoreBundle:Helper:tableheader.html.php', - [ - 'checkall' => 'true', - 'target' => $target, - 'langVar' => 'custom.item', - 'routeBase' => 'custom_item', - 'baseUrl' => $routeSelf, - ] -); - - echo $view->render( - 'MauticCoreBundle:Helper:tableheader.html.php', - [ - 'sessionVar' => $sessionVar, - 'orderBy' => CustomItem::TABLE_ALIAS.'.name', - 'text' => 'mautic.core.name', - 'class' => 'col-custom_item_name', - 'baseUrl' => $routeSelf, - 'target' => $target, - ] - ); - - echo $view->render( - 'MauticCoreBundle:Helper:tableheader.html.php', - [ - 'sessionVar' => $sessionVar, - 'orderBy' => CustomItem::TABLE_ALIAS.'.id', - 'text' => 'mautic.core.id', - 'default' => true, - 'baseUrl' => $routeSelf, - 'target' => $target, - ] - ); - ?> - - getColumnLabels() as $columnLabel): ?> - render('MauticCoreBundle:Helper:tableheader.html.php', ['text' => $columnLabel]); ?> - - - - - - - - - - - - getFields($item->getId()) as $fieldValue): ?> - - - - - - -
    - render('MauticCoreBundle:Helper:list_actions.html.php', ['item' => $item]); ?> - -
    - render( - 'MauticCoreBundle:Helper:publishstatus_icon.html.php', - [ - 'item' => $item, - 'model' => 'custom.item', - ] - ) : ''; ?> - - getName(); ?> - -
    -
    getId(); ?> - render('CustomObjectsBundle:CustomField:value.html.php', ['fieldValue' => $fieldValue]); ?> -
    -
    - - - render('MauticCoreBundle:Helper:noresults.html.php', ['tip' => $lookup ? 'custom.item.link.noresults.tip' : 'custom.object.noresults.tip']); ?> - diff --git a/Views/CustomObject/Form/Panel/_field.html.php b/Views/CustomObject/Form/Panel/_field.html.php deleted file mode 100644 index 97841a964..000000000 --- a/Views/CustomObject/Form/Panel/_field.html.php +++ /dev/null @@ -1,52 +0,0 @@ -vars['data']; -$customField->vars['index'] = $customField->vars['name']; -$order = (int) $customField->vars['value']->getOrder(); -$deleted = !empty($_POST['custom_object']['customFields'][$order]['deleted']) ? 'style="display:none;"' : ''; - -$panelId = !empty($panelId) ? $panelId : (int) $customField->vars['value']->getOrder(); -?> -
    > - -
    - - - - - - - -
    - -
    -
    -
    - row($customField['defaultValue']); ?> -
    -
    -
    -
    - rest($customField); ?> -
    - -
    \ No newline at end of file diff --git a/Views/CustomObject/Form/Panel/checkbox_group.html.php b/Views/CustomObject/Form/Panel/checkbox_group.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/checkbox_group.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/country.html.php b/Views/CustomObject/Form/Panel/country.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/country.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/date.html.php b/Views/CustomObject/Form/Panel/date.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/date.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/datetime.html.php b/Views/CustomObject/Form/Panel/datetime.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/datetime.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/email.html.php b/Views/CustomObject/Form/Panel/email.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/email.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/hidden.html.php b/Views/CustomObject/Form/Panel/hidden.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/hidden.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/html_area.html.php b/Views/CustomObject/Form/Panel/html_area.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/html_area.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/int.html.php b/Views/CustomObject/Form/Panel/int.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/int.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/multiselect.html.php b/Views/CustomObject/Form/Panel/multiselect.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/multiselect.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/phone.html.php b/Views/CustomObject/Form/Panel/phone.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/phone.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/radio_group.html.php b/Views/CustomObject/Form/Panel/radio_group.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/radio_group.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/select.html.php b/Views/CustomObject/Form/Panel/select.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/select.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/text.html.php b/Views/CustomObject/Form/Panel/text.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/text.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/textarea.html.php b/Views/CustomObject/Form/Panel/textarea.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/textarea.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/Form/Panel/url.html.php b/Views/CustomObject/Form/Panel/url.html.php deleted file mode 100644 index 14616e6fc..000000000 --- a/Views/CustomObject/Form/Panel/url.html.php +++ /dev/null @@ -1,5 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:Form\\Panel\\_field.html.php'); diff --git a/Views/CustomObject/_form-fields.html.php b/Views/CustomObject/_form-fields.html.php deleted file mode 100644 index 8f92e0006..000000000 --- a/Views/CustomObject/_form-fields.html.php +++ /dev/null @@ -1,24 +0,0 @@ -children['customFields']->getIterator() as $customField): - $customFieldEntity = $customField->vars['data']; - if (!in_array($customFieldEntity->getId(), $deletedFields, true)) : - echo $view->render( - "CustomObjectsBundle:CustomObject:Form\\Panel\\{$customFieldEntity->getType()}.html.php", - [ - 'customField' => $customField, - 'customObject' => $customObject, - 'panelId' => $panelId ?? null, - ] - ); - endif; -endforeach; -$form->children['customFields']->setRendered(); diff --git a/Views/CustomObject/detail.html.php b/Views/CustomObject/detail.html.php deleted file mode 100644 index f5d9072e4..000000000 --- a/Views/CustomObject/detail.html.php +++ /dev/null @@ -1,149 +0,0 @@ -extend('MauticCoreBundle:Default:content.html.php'); -$view['slots']->set('mauticContent', 'customObject'); -$view['slots']->set('headerTitle', $customObject->getNameSingular()); -$view['slots']->set( - 'actions', - $view->render( - 'MauticCoreBundle:Helper:page_actions.html.php', - ['item' => $customObject] - ) -); - -$view['slots']->set( - 'publishStatus', - $view->render('MauticCoreBundle:Helper:publishstatus_badge.html.php', ['entity' => $customObject]) -); -?> - - -
    - -
    -
    - -
    -
    -
    -
    -
    -
    - - - -
    -
    -
    - - - render( - 'MauticCoreBundle:Helper:details.html.php', - ['entity' => $customObject] -); ?> - -
    -
    -
    -
    - -
    - - -
    - - - - -
    -
    -
    -
    -
    -
    -
    - - trans('custom.item.links.in.time'); ?> -
    -
    -
    - render( - 'MauticCoreBundle:Helper:graph_dateselect.html.php', - ['dateRangeForm' => $dateRangeForm, 'class' => 'pull-right'] -); ?> -
    -
    -
    - render( - 'MauticCoreBundle:Helper:chart.html.php', - ['chartData' => $stats, 'chartType' => 'line', 'chartHeight' => 300] -); ?> -
    -
    -
    -
    -
    - - getCustomContent('details.stats.graph.below', $mauticTemplateVars); ?> - - - - - -
    - -
    - - -
    -
      - getCustomFields() as $field) : ?> -
    • -
      -
      - isRequired() ? 'mautic.core.required' - : 'mautic.core.not_required'; ?> -

      -

      -
      -
      -
      getLabel(); ?>
      -
      -
      - getTypeObject()->getName(); ?> -
      -
      -
    • - -
    -
    - - -
    - -
    - - -
    - - render('MauticCoreBundle:Helper:recentactivity.html.php', ['logs' => $logs]); ?> -
    - -
    diff --git a/Views/CustomObject/form.html.php b/Views/CustomObject/form.html.php deleted file mode 100644 index 09459bb5a..000000000 --- a/Views/CustomObject/form.html.php +++ /dev/null @@ -1,125 +0,0 @@ -extend('MauticCoreBundle:Default:content.html.php'); - -$view['slots']->set('mauticContent', 'customObject'); - -if ($customObject->getId()) { - $header = $view['translator']->trans( - $customObject->getId() ? 'custom.object.edit' : 'custom.object.new', - ['%name%' => $view['translator']->trans($customObject->getName())] - ); -} else { - $header = $view['translator']->trans('custom.object.new'); -} - -$view['slots']->set('headerTitle', $header); -?> - -start($form); ?> - - -
    - -
    -
    -
    - - - -
    -
    -
    -
    - row($form['nameSingular']); ?> - row($form['namePlural']); ?> - -
    -
    - row($form['alias']); ?> -
    -
    -
    -
    - row($form['description']); ?> -
    -
    -
    - -
    - render('MauticFormBundle:Builder:style.html.php'); ?> -
    -
    -
    - -
    -
    -
    - -
    - -
    -

    trans('mautic.form.form.addfield'); ?>

    -
    - -
    -
    - -
    - -
    - -
    - -
    - -
    -
    - row($form['type']); ?> - row($form['masterObject']); ?> - row($form['category']); ?> - row($form['isPublished']); ?> -
    -
    - -
    - -end($form); ?> - -append( - 'modal', - $view->render( - 'MauticCoreBundle:Helper:modal.html.php', - [ - 'id' => 'objectFieldModal', - 'header' => false, - 'footerButtons' => true, - ] - ) - ); diff --git a/Views/CustomObject/index.html.php b/Views/CustomObject/index.html.php deleted file mode 100644 index 747f9e08f..000000000 --- a/Views/CustomObject/index.html.php +++ /dev/null @@ -1,21 +0,0 @@ -extend('MauticCoreBundle:Default:content.html.php'); - -$view['slots']->set('mauticContent', 'customObject'); -$view['slots']->set('headerTitle', $view['translator']->trans('custom.object.title')); -$view['slots']->set('actions', $view->render('MauticCoreBundle:Helper:page_actions.html.php')); -?> - -
    - render( - 'MauticCoreBundle:Helper:list_toolbar.html.php', - [ - // 'searchValue' => $searchValue, - // 'action' => $currentRoute, - ] -); ?> -
    - output('_content'); ?> -
    -
    diff --git a/Views/CustomObject/list.html.php b/Views/CustomObject/list.html.php deleted file mode 100644 index d493f775b..000000000 --- a/Views/CustomObject/list.html.php +++ /dev/null @@ -1,94 +0,0 @@ -extend('CustomObjectsBundle:CustomObject:index.html.php'); -} -?> - -
    - - - - render( - 'MauticCoreBundle:Helper:tableheader.html.php', - [ - 'checkall' => 'true', - 'target' => '#custom-objects-table', - 'langVar' => 'custom.object', - 'routeBase' => 'custom_object', - ] -); - - echo $view->render( - 'MauticCoreBundle:Helper:tableheader.html.php', - [ - 'sessionVar' => $sessionVar, - 'orderBy' => CustomObject::TABLE_ALIAS.'.namePlural', - 'text' => 'mautic.core.name', - 'class' => 'col-custom_object_-name', - ] - ); - - echo $view->render( - 'MauticCoreBundle:Helper:tableheader.html.php', - [ - 'sessionVar' => $sessionVar, - 'orderBy' => CustomObject::TABLE_ALIAS.'.id', - 'text' => 'mautic.core.id', - 'default' => true, - ] - ); - ?> - - - - - - - - - - - -
    - render('MauticCoreBundle:Helper:list_actions.html.php', ['item' => $item]); ?> - -
    - render( - 'MauticCoreBundle:Helper:publishstatus_icon.html.php', - [ - 'item' => $item, - 'model' => 'custom.object', - ] - ); ?> - - getName(); ?> - -
    - getDescription()): ?> -
    - getDescription(); ?> -
    - -
    getId(); ?>
    -
    - - - render('MauticCoreBundle:Helper:noresults.html.php', ['tip' => 'custom.object.noresults.tip']); ?> - diff --git a/Views/SubscribedEvents/Tab/content.html.php b/Views/SubscribedEvents/Tab/content.html.php deleted file mode 100644 index f4d974389..000000000 --- a/Views/SubscribedEvents/Tab/content.html.php +++ /dev/null @@ -1,50 +0,0 @@ - -
    -
    -
    - render( - 'MauticCoreBundle:Helper:search.html.php', - [ - 'searchValue' => $searchValue, - 'action' => $searchRoute, - 'searchId' => $searchId, - 'target' => '#'.$namespace, - 'searchHelp' => '', - ] -); ?> -
    - -
    -
    - Loading... -
    -
    - \ No newline at end of file diff --git a/Views/SubscribedEvents/Tab/link.html.php b/Views/SubscribedEvents/Tab/link.html.php deleted file mode 100644 index a3ca11442..000000000 --- a/Views/SubscribedEvents/Tab/link.html.php +++ /dev/null @@ -1,15 +0,0 @@ - -
  • - - - - - - - escape($view['translator']->trans($title)); ?> - -
  • \ No newline at end of file diff --git a/Views/SubscribedEvents/Tab/modal.html.php b/Views/SubscribedEvents/Tab/modal.html.php deleted file mode 100644 index cb1261e42..000000000 --- a/Views/SubscribedEvents/Tab/modal.html.php +++ /dev/null @@ -1,8 +0,0 @@ -append('modal', $view->render('MauticCoreBundle:Helper:modal.html.php', [ - 'id' => 'customItemLookupModal', - 'size' => 'xl', -])); diff --git a/Views/SubscribedEvents/Timeline/link.html.php b/Views/SubscribedEvents/Timeline/link.html.php deleted file mode 100644 index 89cfec02f..000000000 --- a/Views/SubscribedEvents/Timeline/link.html.php +++ /dev/null @@ -1,17 +0,0 @@ - -
    - -
    - trans('mautic.core.createdby'); ?> -
    -
    - - - -
    - -
    diff --git a/composer.json b/composer.json index 9dc69736b..e238da597 100644 --- a/composer.json +++ b/composer.json @@ -29,11 +29,9 @@ "wiki": "https://github.com/acquia/mc-cs-plugin-custom-objects/wiki" }, "require": { - "php": ">=7.4", + "php": ">=8.0", "ext-mbstring": "*", - "mautic/core-lib": "^4.3" - }, - "require-dev": { + "mautic/core-lib": "^5.0", "theofidry/alice-data-fixtures": "^1.1" }, "scripts": { diff --git a/phpstan-baseline-7.4.neon b/phpstan-baseline-7.4.neon new file mode 100644 index 000000000..480f18008 --- /dev/null +++ b/phpstan-baseline-7.4.neon @@ -0,0 +1,3022 @@ +parameters: + ignoreErrors: + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 3 + path: ../../plugins/CustomObjectsBundle/Command/CustomItemsScheduledExportCommand.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 3 + path: ../../plugins/CustomObjectsBundle/Command/CustomItemsScheduledExportCommand.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 3 + path: ../../plugins/CustomObjectsBundle/Command/GenerateSampleDataCommand.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Command\\\\GenerateSampleDataCommand\\:\\:insertInto\\(\\) has parameter \\$row with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Command/GenerateSampleDataCommand.php + + - + message: "#^Offset 'list' on string in empty\\(\\) does not exist\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomField/SaveController.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomField/SaveController.php + + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomItem/ExportController.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomItem/ExportController.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Form\\\\FormInterface\\:\\:isClicked\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomItem/SaveController.php + + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomObject/DeleteController.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomObject/DeleteController.php + + - + message: "#^Argument of an invalid type string supplied for foreach, only iterables are supported\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomObject/SaveController.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Form\\\\FormInterface\\:\\:isClicked\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomObject/SaveController.php + + - + message: "#^Empty array passed to foreach\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomObject/SaveController.php + + - + message: "#^PHPDoc tag @param for parameter \\$fieldValue with type mixed is not subtype of native type MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/CustomFieldType/CustomFieldTypeInterface.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\CustomObjectsBundle\\:\\:installAllTablesIfMissing\\(\\) has parameter \\$metadata with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/CustomObjectsBundle.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\DTO\\\\CustomItemFieldListData\\:\\:__construct\\(\\) has parameter \\$columns with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/DTO/CustomItemFieldListData.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\DTO\\\\CustomItemFieldListData\\:\\:__construct\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/DTO/CustomItemFieldListData.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\DTO\\\\CustomItemFieldListData\\:\\:getColumnLabels\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/DTO/CustomItemFieldListData.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\DTO\\\\CustomItemFieldListData\\:\\:\\$columns type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/DTO/CustomItemFieldListData.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\DTO\\\\CustomItemFieldListData\\:\\:\\$data type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/DTO/CustomItemFieldListData.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\AbstractCustomFieldValue\\:\\:addValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/AbstractCustomFieldValue.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomField\\:\\:setAlias\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomField.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueInterface\\:\\:addValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomFieldValueInterface.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueInterface\\:\\:setValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomFieldValueInterface.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueOption\\:\\:addValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomFieldValueOption.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueOption\\:\\:setValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomFieldValueOption.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueOption\\:\\:\\$id is unused\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomFieldValueOption.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:addCompanyReference\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:addContactReference\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:addCustomFieldValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:addCustomItemReference\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:createFieldValuesSnapshot\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:getFieldValues\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:recordCustomFieldValueChanges\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setCategory\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setCustomFieldValues\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setCustomFieldValues\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setFieldValues\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setLanguage\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setName\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:\\$fieldValues type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItemExportScheduler\\:\\:\\$id is never written, only read\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItemExportScheduler.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:addCustomField\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:createFieldsSnapshot\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:recordCustomFieldChanges\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:removeCustomField\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setAlias\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setCategory\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setCustomFields\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setDescription\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setId\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setLanguage\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setNamePlural\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setNameSingular\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Event\\\\CustomObjectListFormatEvent\\:\\:__construct\\(\\) has parameter \\$customObjectValues with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Event/CustomObjectListFormatEvent.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Event\\\\CustomObjectListFormatEvent\\:\\:getCustomObjectValues\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Event/CustomObjectListFormatEvent.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Event\\\\CustomObjectListFormatEvent\\:\\:\\$customObjectValues type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Event/CustomObjectListFormatEvent.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CampaignSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CampaignSubscriber\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CampaignSubscriber.php + + - + message: "#^Variable \\$contact in empty\\(\\) always exists and is not falsy\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CampaignSubscriber.php + + - + message: "#^Parameter \\#2 \\$bundle of method Mautic\\\\LeadBundle\\\\Entity\\\\LeadEventLogRepository\\:\\:getEvents\\(\\) expects null, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ContactSubscriber.php + + - + message: "#^Parameter \\#3 \\$object of method Mautic\\\\LeadBundle\\\\Entity\\\\LeadEventLogRepository\\:\\:getEvents\\(\\) expects null, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ContactSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CustomItemButtonSubscriber\\:\\:defineEditLinkFormButton\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CustomItemButtonSubscriber.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CustomItemXrefContactSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CustomObjectButtonSubscriber\\:\\:defineCreateNewCustomItemButton\\(\\) should return array\\ but returns array\\\\|int\\|string\\>\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CustomObjectButtonSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CustomObjectButtonSubscriber\\:\\:defineViewCustomItemsButton\\(\\) should return array\\ but returns array\\\\|int\\|string\\>\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CustomObjectButtonSubscriber.php + + - + message: "#^Call to an undefined method Psr\\\\Log\\\\LoggerInterface\\:\\:addError\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/DynamicContentSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\DynamicContentSubscriber\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/DynamicContentSubscriber.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/EventListener/FilterOperatorSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\FilterOperatorSubscriber\\:\\:onOperatorsGenerate\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/FilterOperatorSubscriber.php + + - + message: "#^Call to an undefined method Mautic\\\\LeadBundle\\\\Event\\\\ImportProcessEvent\\:\\:addWarning\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ImportSubscriber.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:addPrefixToColumnLabel\\(\\) has parameter \\$columns with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:addPrefixToColumnLabel\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:getCompanyColumns\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:getContexts\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:getCustomObjectColumns\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:getLeadColumns\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:getStandardColumns\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:\\$customObjects is never written, only read\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersDictionarySubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\SegmentFiltersDictionarySubscriber\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersDictionarySubscriber.php + + - + message: "#^Access to undefined constant Mautic\\\\LeadBundle\\\\Segment\\\\ContactSegmentFilterFactory\\:\\:CUSTOM_OPERATOR\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersMergeSubscriber.php + + - + message: "#^Call to method getFilters\\(\\) on an unknown class Mautic\\\\LeadBundle\\\\Event\\\\LeadListMergeFiltersEvent\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersMergeSubscriber.php + + - + message: "#^Call to method setFilters\\(\\) on an unknown class Mautic\\\\LeadBundle\\\\Event\\\\LeadListMergeFiltersEvent\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersMergeSubscriber.php + + - + message: "#^Parameter \\$event of method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\SegmentFiltersMergeSubscriber\\:\\:mergeCustomObjectFilters\\(\\) has invalid type Mautic\\\\LeadBundle\\\\Event\\\\LeadListMergeFiltersEvent\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersMergeSubscriber.php + + - + message: "#^Cannot access offset 'alias' on int\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SerializerSubscriber.php + + - + message: "#^Cannot access offset 'id' on int\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/EventListener/SerializerSubscriber.php + + - + message: "#^Left side of && is always true\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/TokenSubscriber.php + + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/TokenSubscriber.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/EventListener/TokenSubscriber.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/TokenSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Exception\\\\InUseException\\:\\:getSegmentList\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Exception/InUseException.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Exception\\\\InUseException\\:\\:setSegmentList\\(\\) has parameter \\$segmentList with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Exception/InUseException.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Exception\\\\InUseException\\:\\:\\$segmentList type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Exception/InUseException.php + + - + message: "#^Argument of an invalid type string supplied for foreach, only iterables are supported\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/DataTransformer/OptionsTransformer.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:transform\\(\\) should return array\\ but returns array\\\\>\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/DataTransformer/OptionsTransformer.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:transform\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/DataTransformer/OptionsTransformer.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/DataTransformer/OptionsTransformer.php + + - + message: "#^PHPDoc tag @var for variable \\$option has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/DataTransformer/OptionsTransformer.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\Type\\\\CustomField\\\\OptionsType\\:\\:buildView\\(\\) has parameter \\$form with no value type specified in iterable type Symfony\\\\Component\\\\Form\\\\FormInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Type/CustomField/OptionsType.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\Type\\\\CustomFieldType\\:\\:createDefaultValueInput\\(\\) has parameter \\$form with no value type specified in iterable type Symfony\\\\Component\\\\Form\\\\FormInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Type/CustomFieldType.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Type/CustomFieldType.php + + - + message: "#^Variable \\$customFields in empty\\(\\) always exists and is not falsy\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Type/CustomObjectType.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\Validator\\\\Constraints\\\\CustomObjectTypeValues\\:\\:\\$missingMasterObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Validator/Constraints/CustomObjectTypeValues.php + + - + message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$missingMasterObject\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Validator/Constraints/CustomObjectTypeValuesValidator.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\Validator\\\\Constraints\\\\CustomObjectTypeValuesValidator\\:\\:validate\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Validator/Constraints/CustomObjectTypeValuesValidator.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 5 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterFactory.php + + - + message: "#^Call to an undefined method Mautic\\\\LeadBundle\\\\Segment\\\\ContactSegmentFilterCrate\\:\\:getMergedProperty\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 5 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\QueryFilterHelper\\:\\:addOperatorExpression\\(\\) has parameter \\$value with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\QueryFilterHelper\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\QueryFilterHelper\\:\\:hasQueryJoinAlias\\(\\) has parameter \\$alias with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Parameter \\#3 \\$type of method Mautic\\\\LeadBundle\\\\Segment\\\\Query\\\\QueryBuilder\\:\\:setParameter\\(\\) expects string\\|null, int given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:conjunctionList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:format\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:formatAndList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:formatBulletList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:formatDefault\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:formatOrList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:formatOrderedList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:htmlList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:removeEmptyValues\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:removeEmptyValues\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldModel\\:\\:fetchCustomFieldsForObject\\(\\) should return array\\ but returns Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator&iterable\\\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldModel\\:\\:fetchEntities\\(\\) should return Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator&iterable\\ but returns array\\|Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldModel.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldOptionModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldValueModel\\:\\:buildItemsListData\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldValueModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldValueModel\\:\\:fetchItemsListData\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldValueModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldValueModel\\:\\:transformItemsListDataResult\\(\\) has parameter \\$result with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldValueModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldValueModel\\:\\:transformItemsListDataResult\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldValueModel.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomItemExportSchedulerModel.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomItemModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomItemModel\\:\\:getArrayTableData\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomItemModel.php + + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 12 + path: ../../plugins/CustomObjectsBundle/Model/CustomItemModel.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 12 + path: ../../plugins/CustomObjectsBundle/Model/CustomItemModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomObjectModel\\:\\:fetchAllPublishedEntities\\(\\) should return array\\ but returns Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator&iterable\\\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomObjectModel\\:\\:fetchEntities\\(\\) should return Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator&iterable\\ but returns array\\|Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomObjectModel\\:\\:getMasterCustomObjects\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 4 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 4 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomObjectModel\\:\\:\\$listModel is never read, only written\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\CustomItemRouteProvider\\:\\:buildListRoute\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Provider/CustomItemRouteProvider.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:setValue\\(\\) has parameter \\$value with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Unsafe access to private constant MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:KEY_FILTER through static\\:\\:\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Unsafe access to private constant MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:KEY_LIMIT through static\\:\\:\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Unsafe access to private constant MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:KEY_ORDER_BY through static\\:\\:\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Unsafe access to private constant MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:KEY_ORDER_BY_DIR through static\\:\\:\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Unsafe access to private constant MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:KEY_PAGE through static\\:\\:\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Report\\\\ReportColumnsBuilder\\:\\:getColumns\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Report/ReportColumnsBuilder.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Report\\\\ReportColumnsBuilder\\:\\:getJoinableColumns\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Report/ReportColumnsBuilder.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Report\\\\ReportColumnsBuilder\\:\\:\\$columnTypeMapping type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Report/ReportColumnsBuilder.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Report\\\\ReportColumnsBuilder\\:\\:\\$columns type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Report/ReportColumnsBuilder.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Repository\\\\CustomItemRepository\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Repository/CustomItemRepository.php + + - + message: "#^Call to method getId\\(\\) on an unknown class MauticPlugin\\\\CustomObjectsBundle\\\\Repository\\\\CustomField\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Repository/CustomObjectRepository.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Repository\\\\CustomObjectRepository\\:\\:getMasterObjectChoices\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Repository/CustomObjectRepository.php + + - + message: "#^PHPDoc tag @var for variable \\$customField contains unknown class MauticPlugin\\\\CustomObjectsBundle\\\\Repository\\\\CustomField\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Repository/CustomObjectRepository.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Security\\\\Permissions\\\\CustomObjectPermissions\\:\\:buildForm\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Security/Permissions/CustomObjectPermissions.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Security\\\\Permissions\\\\CustomObjectPermissions\\:\\:buildForm\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Security/Permissions/CustomObjectPermissions.php + + - + message: "#^Parameter \\#2 \\$level of method Mautic\\\\CoreBundle\\\\Security\\\\Permissions\\\\AbstractPermissions\\:\\:addExtendedFormFields\\(\\) expects string, int\\|null given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Security/Permissions/CustomObjectPermissions.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/CustomFieldFilterQueryBuilder.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/CustomItemNameFilterQueryBuilder.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/CustomObjectMergedFilterQueryBuilder.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/QueryFilterFactory.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\Filter\\\\QueryFilterFactory\\:\\:configureQueryBuilderFromSegmentFilter\\(\\) has parameter \\$segmentFilter with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/QueryFilterFactory.php + + - + message: "#^PHPDoc tag @throws with type MauticPlugin\\\\CustomObjectsBundle\\\\Exception\\\\InvalidSegmentFilterException\\|MauticPlugin\\\\CustomObjectsBundle\\\\Exception\\\\NotFoundException\\|MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\Filter\\\\Exception is not subtype of Throwable$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/QueryFilterFactory.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\UnionQueryContainer\\:\\:getParameterTypes\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/UnionQueryContainer.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\UnionQueryContainer\\:\\:getParameters\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/UnionQueryContainer.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\UnionQueryContainer\\:\\:\\$parameterTypes type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/UnionQueryContainer.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\UnionQueryContainer\\:\\:\\$parameters type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/UnionQueryContainer.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\AbstractApiPlatformFunctionalTest\\:\\:createEntity\\(\\) has parameter \\$payload with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\AbstractApiPlatformFunctionalTest\\:\\:requestEntity\\(\\) has parameter \\$payload with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\AbstractApiPlatformFunctionalTest\\:\\:setPermission\\(\\) has parameter \\$permissionArray with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\AbstractApiPlatformFunctionalTest\\:\\:updateEntity\\(\\) has parameter \\$payload with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\AbstractApiPlatformFunctionalTest\\:\\:\\$clientServer type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getCRUDProvider\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getCRUDWithOptionsProvider\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getCreatePayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getCreateWithOptionsPayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getEditPayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getEditWithOptionsPayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:runTestCustomFieldCRUD\\(\\) has parameter \\$permissions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:runTestCustomFieldWithOptionsCRUD\\(\\) has parameter \\$permissions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:runTestCustomFieldWithOptionsCRUD\\(\\) has parameter \\$retrievedOptions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:runTestCustomFieldWithOptionsCRUD\\(\\) has parameter \\$updatedOptions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldOptionFunctionalTest\\:\\:getCRUDProvider\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldOptionFunctionalTest\\:\\:getCreatePayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldOptionFunctionalTest\\:\\:getEditPayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldOptionFunctionalTest\\:\\:runTestCustomFieldOptionCRUD\\(\\) has parameter \\$permissions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomObjectFunctionalTest\\:\\:getCRUDProvider\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomObjectFunctionalTest\\:\\:getCreatePayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomObjectFunctionalTest\\:\\:getEditPayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomObjectFunctionalTest\\:\\:runTestCustomObjectCRUD\\(\\) has parameter \\$permissions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Controller/CustomItemListControllerShownFieldTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:testDeleteChildObject\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Call to an undefined method MauticPlugin\\\\CustomObjectsBundle\\\\Repository\\\\CustomObjectRepository\\:\\:findOneById\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Controller/CustomObjectFormTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\Controller\\\\CustomObjectFormTest\\:\\:assertCustomObject\\(\\) has parameter \\$expected with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Controller/CustomObjectFormTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\EventListener\\\\FilterOperatorSubscriberTest\\:\\:testIfNewOperatorNotInCustomObjectsAddedinSegmentFilter\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/EventListener/FilterOperatorSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\EventListener\\\\FilterOperatorSubscriberTest\\:\\:testIfProperContactsAreAddedinSegmentWithNotInCustomObjectsFilter\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/EventListener/FilterOperatorSubscriberTest.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/EventListener/ImportSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\Helper\\\\QueryFilterHelperTest\\:\\:assertMatchWhere\\(\\) has parameter \\$filter with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Helper/QueryFilterHelperTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\Segment\\\\Query\\\\Filter\\\\CustomFieldFilterQueryBuilderTest\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\Segment\\\\Query\\\\Filter\\\\CustomItemNameFilterQueryBuilderTest\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^Call to an undefined method Mautic\\\\LeadBundle\\\\Entity\\\\LeadRepository\\:\\:findOneByEmail\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Segment/Query/Filter/CustomItemRelationQueryBuilderTestCase.php + + - + message: "#^Call to an undefined method Mautic\\\\CoreBundle\\\\Controller\\\\MauticController&Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\Controller\\:\\:setRequest\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Call to an undefined method Mautic\\\\CoreBundle\\\\Controller\\\\MauticController&Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\Controller\\:\\:setTranslator\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\ControllerTestCase\\:\\:\\$request has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\ControllerTestCase\\:\\:\\$requestStack has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\ControllerTestCase\\:\\:\\$router \\(Symfony\\\\Component\\\\Routing\\\\Router\\) does not accept PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Symfony\\\\Component\\\\Routing\\\\RouterInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\ControllerTestCase\\:\\:\\$session has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$fieldId with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$fieldType with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$mapExtras with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$objectId with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$panelCount with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$panelId with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$customFieldFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$fieldRouteProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$formController has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$objectRouteProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$customFieldFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$fieldRouteProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$saveController has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\CancelControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/CancelControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\CancelControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/CancelControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\CancelControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/CancelControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Call to an undefined method Mautic\\\\CoreBundle\\\\Helper\\\\UserHelper\\:\\:expects\\(\\)\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/FormControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\FormControllerTest\\:\\:testEditActionWhenTheItemIsLocked\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/FormControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\FormControllerTest\\:\\:testEditWithRedirectToContactActionWhenTheItemIsLocked\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\FormControllerTest\\:\\:\\$form type has no value type specified in iterable type Symfony\\\\Component\\\\Form\\\\FormInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LinkControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LinkControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LinkControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LinkControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LinkControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LinkControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ListControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ListControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ListControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ListControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ListControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LookupControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LookupControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LookupControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LookupControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LookupControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LookupControllerTest.php + + - + message: "#^Call to an undefined method Mautic\\\\CoreBundle\\\\Helper\\\\UserHelper\\:\\:expects\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/SaveControllerTest.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Routing\\\\Router\\:\\:expects\\(\\)\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\SaveControllerTest\\:\\:\\$form type has no value type specified in iterable type Symfony\\\\Component\\\\Form\\\\FormInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$auditLog has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$customItemXrefContactModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\CancelControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/CancelControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\CancelControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/CancelControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\CancelControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/CancelControllerTest.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:expects\\(\\)\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:\\$leadListIndex is never read, only written\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$customFieldTypeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$lockFlashMessageHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ListControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ListControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ListControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ListControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$customFieldTypeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$lockFlashMessageHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$optionsToStringTransformer has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$paramsToStringTransformer has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$auditLog has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractCustomFieldTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractCustomFieldTypeTest\\:\\:\\$fieldType \\(MauticPlugin\\\\CustomObjectsBundle\\\\CustomFieldType\\\\EmailType\\) does not accept MauticPlugin\\\\CustomObjectsBundle\\\\CustomFieldType\\\\AbstractCustomFieldType&PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractCustomFieldTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractCustomFieldTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php + + - + message: "#^Parameter \\#3 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\CustomFieldType\\\\AbstractMultivalueType\\:\\:createValueEntity\\(\\) expects null, array\\ given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractMultivalueTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractMultivalueTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractMultivalueTypeTest\\:\\:\\$provider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractMultivalueTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractTextTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractTextTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractTextTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractTextTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\CountryTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/CountryTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTimeTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTimeTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTimeTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTimeTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTimeTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTimeTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTimeTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTimeTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\EmailTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/EmailTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\EmailTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/EmailTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\IntTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/IntTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\IntTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/IntTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\IntTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/IntTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\IntTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/IntTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\MultiselectTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/MultiselectTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\PhoneTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/PhoneTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\PhoneTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/PhoneTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\SelectTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/SelectTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\SelectTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/SelectTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\SelectTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/SelectTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\SelectTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/SelectTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\UrlTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/UrlTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\UrlTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/UrlTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\AbstractCustomFieldValueTest\\:\\:\\$abstractCFValue has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/AbstractCustomFieldValueTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\AbstractCustomFieldValueTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/AbstractCustomFieldValueTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\AbstractCustomFieldValueTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/AbstractCustomFieldValueTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\AbstractCustomFieldValueTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/AbstractCustomFieldValueTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomField\\\\ParamsTest\\:\\:testConstructorAndToArray\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomField/ParamsTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomField\\\\ParamsTest\\:\\:testGettersSetters\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomField/ParamsTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomField\\\\ParamsTest\\:\\:testToArrayRemovingFalseAndNullValues\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomField/ParamsTest.php + + - + message: "#^Parameter \\#1 \\$array \\(array\\{placeholder\\: null\\}\\) to function array_filter contains falsy values only, the result will always be an empty array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomField/ParamsTest.php + + - + message: "#^Unable to resolve the template type RealInstanceType in call to method PHPUnit\\\\Framework\\\\TestCase\\:\\:createMock\\(\\)$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldFactoryTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldOptionTest\\:\\:testArrayAccessor\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldOptionTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldOptionTest\\:\\:testConstructorAndToArray\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldOptionTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldOptionTest\\:\\:testGettersSetters\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldOptionTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldTest\\:\\:testCanHaveMultipleValuesForCheckboxType\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldTest\\:\\:testCanHaveMultipleValuesForDateType\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldTest\\:\\:testDefaultValueTransformation\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomObjectTest\\:\\:testGetCfByOrder\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomObjectTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ApiSubscriberTest\\:\\:\\$apiEntityEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ApiSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ApiSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ApiSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ApiSubscriberTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ApiSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ApiSubscriberTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ApiSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ApiSubscriberTest\\:\\:\\$request has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ApiSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$assetsHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$assetsSubscriber has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$getResponseEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$request has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$auditLogModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$auditLogSubscriber has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$customItemEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$customObjectEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$ipLookupHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$campaignBuilderEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$campaignExecutionEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$contact has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$queryFilterFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$queryFilterHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$segmentQueryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$statement has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$leadEventLogRepo has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$leadTimelineEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactTabSubscriberTest\\:\\:testSubscriberEvents\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactTabSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomFieldPostLoadSubscriberTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomFieldPostLoadSubscriberTest\\:\\:\\$customFieldTypeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomFieldPostLoadSubscriberTest\\:\\:\\$event has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomFieldPostLoadSubscriberTest\\:\\:\\$subscriber has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$contact has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$discoveryEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$event has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$listDbalEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$listEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$queryBuilderDbal has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$xref has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$customItemA has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$customItemB has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$discoveryEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$event has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$expr has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$listEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$xref has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$event has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$itemPermissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$itemRouteProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$objectPermissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$objectRouteProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/FilterOperatorSubscriberTest.php + + - + message: "#^PHPDoc tag @var for variable \\$formMock has no value type specified in iterable type Symfony\\\\Component\\\\Form\\\\FormInterface\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/FilterOperatorSubscriberTest.php + + - + message: "#^Parameter \\#1 \\$form of class Mautic\\\\LeadBundle\\\\Event\\\\FormAdjustmentEvent constructor expects iterable\\&Symfony\\\\Component\\\\Form\\\\FormInterface, PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\|Symfony\\\\Component\\\\Form\\\\FormInterface given\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/FilterOperatorSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$customFieldRepository has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$customItemImportModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$import has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$importInitEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$importMappingEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$importProcessEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$importValidateEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\MenuSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/MenuSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\MenuSubscriberTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/MenuSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\MenuSubscriberTest\\:\\:\\$menuEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/MenuSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ReportSubscriberTest\\:\\:getCustomObjectsCollection\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ReportSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ReportSubscriberTest\\:\\:testThatIdDoesntProcessContextsWithEmptyOrNotIntCustomObjectsID\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ReportSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ReportSubscriberTest\\:\\:testThatIdDoesntProcessNotExistingCustomObjects\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ReportSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ReportSubscriberTest\\:\\:testThatOnReportGenerateMethodDoesntProcessWrongContexts\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ReportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$customItemXrefContactRepository has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$objectEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$request has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$requestStack has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Exception\\\\InvalidCustomObjectFormatListExceptionTest\\:\\:testAll\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Exception/InvalidCustomObjectFormatListExceptionTest.php + + - + message: "#^Parameter \\#1 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:reverseTransform\\(\\) expects array\\, array\\\\>\\> given\\.$#" + count: 4 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:transform\\(\\) expects Doctrine\\\\ORM\\\\PersistentCollection&iterable\\, Doctrine\\\\Common\\\\Collections\\\\ArrayCollection\\<\\*NEVER\\*, \\*NEVER\\*\\> given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:transform\\(\\) expects Doctrine\\\\ORM\\\\PersistentCollection&iterable\\, Doctrine\\\\Common\\\\Collections\\\\ArrayCollection\\ given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:transform\\(\\) expects Doctrine\\\\ORM\\\\PersistentCollection&iterable\\, null given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^Parameter \\#1 \\$params of method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\ParamsToStringTransformer\\:\\:transform\\(\\) expects MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomField\\\\Params\\|null, array given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/DataTransformer/ParamsToStringTransformerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CampaignConditionFieldValueTypeTest\\:\\:testConfigureOptions\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CampaignConditionFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$customFieldType has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$customFieldValue has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$formBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$optionsResolver has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomObjectTypeTest\\:\\:buildForm\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomObjectTypeTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomObjectTypeTest\\:\\:testBuildFormExistingObject\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomObjectTypeTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomObjectTypeTest\\:\\:testBuildFormNewObject\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomObjectTypeTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomObjectTypeTest\\:\\:testConfigureOptions\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomObjectTypeTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Validator\\\\CustomObjectTypeValuesTest\\:\\:testGetTargets\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Validator\\\\CustomObjectTypeValuesTest\\:\\:testValidatedBy\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesTest.php + + - + message: "#^Access to an undefined property PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\|Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$missingMasterObject\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Validator\\\\CustomObjectTypeValuesValidatorTest\\:\\:testValidateIgnoreCompletely\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Validator\\\\CustomObjectTypeValuesValidatorTest\\:\\:testValidateIgnoreMasterObject\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Validator\\\\CustomObjectTypeValuesValidatorTest\\:\\:testValidateNoCustomObject\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\CustomFieldQueryBuilder\\\\CalculatorTest\\:\\:assertMatrixEquals\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/CustomFieldQueryBuilder/CalculatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\CustomFieldQueryBuilder\\\\CalculatorTest\\:\\:assertMatrixEquals\\(\\) has parameter \\$expectedMatrix with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/CustomFieldQueryBuilder/CalculatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\CustomFieldQueryBuilder\\\\CalculatorTest\\:\\:getSuffix\\(\\) has parameter \\$decisionValue with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/CustomFieldQueryBuilder/CalculatorTest.php + + - + message: "#^Parameter \\#4 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\QueryFilterHelper\\:\\:addCustomObjectNameExpression\\(\\) expects string\\|null, int given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/QueryFilterHelperTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:testAvailableFormats\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:testFormatManyValues\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:testFormatOneValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:testIsValidFormat\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:\\$availableFormats has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:\\$manyValues has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:\\$noValues has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:\\$oneValue has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldOptionModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldOptionModelTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldOptionModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldOptionModelTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldOptionModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldOptionModelTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldOptionModelTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$customFieldValueModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$statement has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$validator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$violationList has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$customFieldValueModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$customItemPermissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$customItemRepository has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$dbalQueryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$dispatcher has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$statement has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$user has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$userHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$validator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$violationList has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemXrefContactModelTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemXrefContactModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemXrefContactModelTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemXrefContactModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemXrefContactModelTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemXrefContactModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemXrefContactModelTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemXrefContactModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemXrefContactModelTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemXrefContactModelTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:testGetMasterCustomObjects\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$customObjectPermissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$customObjectRepository has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$databasePlatform has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$dispatcher has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$queryBuilderDbal has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$statement has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$user has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$userHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomFieldRouteProviderTest\\:\\:\\$router has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomFieldRouteProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemPermissionProviderTest\\:\\:\\$corePermissions has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemPermissionProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemPermissionProviderTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemPermissionProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemPermissionProviderTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemPermissionProviderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemRouteProviderTest\\:\\:testThatBuildContactViewRouteReturnsCorrectUrl\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemRouteProviderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemRouteProviderTest\\:\\:testThatBuildEditRouteWithRedirectToContactReturnsCorrectUrl\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemRouteProviderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemRouteProviderTest\\:\\:testThatBuildNewRouteWithRedirectToContactReturnsCorrectUrl\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemRouteProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemRouteProviderTest\\:\\:\\$router has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemRouteProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomObjectPermissionProviderTest\\:\\:\\$entity has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomObjectPermissionProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomObjectPermissionProviderTest\\:\\:\\$permissions has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomObjectPermissionProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomObjectRouteProviderTest\\:\\:\\$router has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomObjectRouteProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomFieldRepositoryTest\\:\\:\\$classMetadata has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomFieldRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomFieldRepositoryTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomFieldRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomFieldRepositoryTest\\:\\:\\$expression has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomFieldRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomFieldRepositoryTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomFieldRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomFieldRepositoryTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomFieldRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$contact has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$expr has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$classMetadata has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$contact has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$expr has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$expressionBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$queryBuilderDbal has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$statement has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Segment\\\\Query\\\\Filter\\\\CustomItemNameFilterQueryBuilderTest\\:\\:parameterValueProvider\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Segment\\\\Query\\\\Filter\\\\CustomItemNameFilterQueryBuilderTest\\:\\:testApplyQuery\\(\\) has parameter \\$parameterValue with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^PHPDoc tag @param has invalid value \\(\\$parameterValue\\)\\: Unexpected token \"\\$parameterValue\", expected type at offset 69$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 3 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/Filter/QueryFilterFactoryTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Segment\\\\Query\\\\UnionQueryContainerTest\\:\\:testParameterTypesCheck\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/UnionQueryContainerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Segment\\\\Query\\\\UnionQueryContainerTest\\:\\:testParametersCheck\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/UnionQueryContainerTest.php + + - + message: "#^Parameter \\#3 \\$type of method Mautic\\\\LeadBundle\\\\Segment\\\\Query\\\\QueryBuilder\\:\\:setParameter\\(\\) expects string\\|null, int given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/UnionQueryContainerTest.php + diff --git a/phpstan-baseline-8.0.neon b/phpstan-baseline-8.0.neon new file mode 100644 index 000000000..480f18008 --- /dev/null +++ b/phpstan-baseline-8.0.neon @@ -0,0 +1,3022 @@ +parameters: + ignoreErrors: + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 3 + path: ../../plugins/CustomObjectsBundle/Command/CustomItemsScheduledExportCommand.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 3 + path: ../../plugins/CustomObjectsBundle/Command/CustomItemsScheduledExportCommand.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 3 + path: ../../plugins/CustomObjectsBundle/Command/GenerateSampleDataCommand.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Command\\\\GenerateSampleDataCommand\\:\\:insertInto\\(\\) has parameter \\$row with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Command/GenerateSampleDataCommand.php + + - + message: "#^Offset 'list' on string in empty\\(\\) does not exist\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomField/SaveController.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomField/SaveController.php + + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomItem/ExportController.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomItem/ExportController.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Form\\\\FormInterface\\:\\:isClicked\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomItem/SaveController.php + + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomObject/DeleteController.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomObject/DeleteController.php + + - + message: "#^Argument of an invalid type string supplied for foreach, only iterables are supported\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomObject/SaveController.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Form\\\\FormInterface\\:\\:isClicked\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomObject/SaveController.php + + - + message: "#^Empty array passed to foreach\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Controller/CustomObject/SaveController.php + + - + message: "#^PHPDoc tag @param for parameter \\$fieldValue with type mixed is not subtype of native type MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/CustomFieldType/CustomFieldTypeInterface.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\CustomObjectsBundle\\:\\:installAllTablesIfMissing\\(\\) has parameter \\$metadata with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/CustomObjectsBundle.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\DTO\\\\CustomItemFieldListData\\:\\:__construct\\(\\) has parameter \\$columns with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/DTO/CustomItemFieldListData.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\DTO\\\\CustomItemFieldListData\\:\\:__construct\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/DTO/CustomItemFieldListData.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\DTO\\\\CustomItemFieldListData\\:\\:getColumnLabels\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/DTO/CustomItemFieldListData.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\DTO\\\\CustomItemFieldListData\\:\\:\\$columns type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/DTO/CustomItemFieldListData.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\DTO\\\\CustomItemFieldListData\\:\\:\\$data type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/DTO/CustomItemFieldListData.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\AbstractCustomFieldValue\\:\\:addValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/AbstractCustomFieldValue.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomField\\:\\:setAlias\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomField.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueInterface\\:\\:addValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomFieldValueInterface.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueInterface\\:\\:setValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomFieldValueInterface.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueOption\\:\\:addValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomFieldValueOption.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueOption\\:\\:setValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomFieldValueOption.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomFieldValueOption\\:\\:\\$id is unused\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomFieldValueOption.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:addCompanyReference\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:addContactReference\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:addCustomFieldValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:addCustomItemReference\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:createFieldValuesSnapshot\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:getFieldValues\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:recordCustomFieldValueChanges\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setCategory\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setCustomFieldValues\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setCustomFieldValues\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setFieldValues\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setLanguage\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:setName\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItem\\:\\:\\$fieldValues type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItem.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomItemExportScheduler\\:\\:\\$id is never written, only read\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomItemExportScheduler.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:addCustomField\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:createFieldsSnapshot\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:recordCustomFieldChanges\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:removeCustomField\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setAlias\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setCategory\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setCustomFields\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setDescription\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setId\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setLanguage\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setNamePlural\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject\\:\\:setNameSingular\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Entity/CustomObject.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Event\\\\CustomObjectListFormatEvent\\:\\:__construct\\(\\) has parameter \\$customObjectValues with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Event/CustomObjectListFormatEvent.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Event\\\\CustomObjectListFormatEvent\\:\\:getCustomObjectValues\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Event/CustomObjectListFormatEvent.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Event\\\\CustomObjectListFormatEvent\\:\\:\\$customObjectValues type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Event/CustomObjectListFormatEvent.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CampaignSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CampaignSubscriber\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CampaignSubscriber.php + + - + message: "#^Variable \\$contact in empty\\(\\) always exists and is not falsy\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CampaignSubscriber.php + + - + message: "#^Parameter \\#2 \\$bundle of method Mautic\\\\LeadBundle\\\\Entity\\\\LeadEventLogRepository\\:\\:getEvents\\(\\) expects null, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ContactSubscriber.php + + - + message: "#^Parameter \\#3 \\$object of method Mautic\\\\LeadBundle\\\\Entity\\\\LeadEventLogRepository\\:\\:getEvents\\(\\) expects null, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ContactSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CustomItemButtonSubscriber\\:\\:defineEditLinkFormButton\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CustomItemButtonSubscriber.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CustomItemXrefContactSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CustomObjectButtonSubscriber\\:\\:defineCreateNewCustomItemButton\\(\\) should return array\\ but returns array\\\\|int\\|string\\>\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CustomObjectButtonSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CustomObjectButtonSubscriber\\:\\:defineViewCustomItemsButton\\(\\) should return array\\ but returns array\\\\|int\\|string\\>\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/CustomObjectButtonSubscriber.php + + - + message: "#^Call to an undefined method Psr\\\\Log\\\\LoggerInterface\\:\\:addError\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/DynamicContentSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\DynamicContentSubscriber\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/DynamicContentSubscriber.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/EventListener/FilterOperatorSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\FilterOperatorSubscriber\\:\\:onOperatorsGenerate\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/FilterOperatorSubscriber.php + + - + message: "#^Call to an undefined method Mautic\\\\LeadBundle\\\\Event\\\\ImportProcessEvent\\:\\:addWarning\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ImportSubscriber.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:addPrefixToColumnLabel\\(\\) has parameter \\$columns with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:addPrefixToColumnLabel\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:getCompanyColumns\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:getContexts\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:getCustomObjectColumns\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:getLeadColumns\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:getStandardColumns\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:\\$customObjects is never written, only read\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/ReportSubscriber.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersDictionarySubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\SegmentFiltersDictionarySubscriber\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersDictionarySubscriber.php + + - + message: "#^Access to undefined constant Mautic\\\\LeadBundle\\\\Segment\\\\ContactSegmentFilterFactory\\:\\:CUSTOM_OPERATOR\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersMergeSubscriber.php + + - + message: "#^Call to method getFilters\\(\\) on an unknown class Mautic\\\\LeadBundle\\\\Event\\\\LeadListMergeFiltersEvent\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersMergeSubscriber.php + + - + message: "#^Call to method setFilters\\(\\) on an unknown class Mautic\\\\LeadBundle\\\\Event\\\\LeadListMergeFiltersEvent\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersMergeSubscriber.php + + - + message: "#^Parameter \\$event of method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\SegmentFiltersMergeSubscriber\\:\\:mergeCustomObjectFilters\\(\\) has invalid type Mautic\\\\LeadBundle\\\\Event\\\\LeadListMergeFiltersEvent\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SegmentFiltersMergeSubscriber.php + + - + message: "#^Cannot access offset 'alias' on int\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/SerializerSubscriber.php + + - + message: "#^Cannot access offset 'id' on int\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/EventListener/SerializerSubscriber.php + + - + message: "#^Left side of && is always true\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/TokenSubscriber.php + + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/TokenSubscriber.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/EventListener/TokenSubscriber.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/EventListener/TokenSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Exception\\\\InUseException\\:\\:getSegmentList\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Exception/InUseException.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Exception\\\\InUseException\\:\\:setSegmentList\\(\\) has parameter \\$segmentList with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Exception/InUseException.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Exception\\\\InUseException\\:\\:\\$segmentList type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Exception/InUseException.php + + - + message: "#^Argument of an invalid type string supplied for foreach, only iterables are supported\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/DataTransformer/OptionsTransformer.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:transform\\(\\) should return array\\ but returns array\\\\>\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/DataTransformer/OptionsTransformer.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:transform\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/DataTransformer/OptionsTransformer.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/DataTransformer/OptionsTransformer.php + + - + message: "#^PHPDoc tag @var for variable \\$option has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/DataTransformer/OptionsTransformer.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\Type\\\\CustomField\\\\OptionsType\\:\\:buildView\\(\\) has parameter \\$form with no value type specified in iterable type Symfony\\\\Component\\\\Form\\\\FormInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Type/CustomField/OptionsType.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\Type\\\\CustomFieldType\\:\\:createDefaultValueInput\\(\\) has parameter \\$form with no value type specified in iterable type Symfony\\\\Component\\\\Form\\\\FormInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Type/CustomFieldType.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Type/CustomFieldType.php + + - + message: "#^Variable \\$customFields in empty\\(\\) always exists and is not falsy\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Type/CustomObjectType.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\Validator\\\\Constraints\\\\CustomObjectTypeValues\\:\\:\\$missingMasterObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Validator/Constraints/CustomObjectTypeValues.php + + - + message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$missingMasterObject\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Validator/Constraints/CustomObjectTypeValuesValidator.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\Validator\\\\Constraints\\\\CustomObjectTypeValuesValidator\\:\\:validate\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Form/Validator/Constraints/CustomObjectTypeValuesValidator.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 5 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterFactory.php + + - + message: "#^Call to an undefined method Mautic\\\\LeadBundle\\\\Segment\\\\ContactSegmentFilterCrate\\:\\:getMergedProperty\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 5 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\QueryFilterHelper\\:\\:addOperatorExpression\\(\\) has parameter \\$value with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\QueryFilterHelper\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\QueryFilterHelper\\:\\:hasQueryJoinAlias\\(\\) has parameter \\$alias with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Parameter \\#3 \\$type of method Mautic\\\\LeadBundle\\\\Segment\\\\Query\\\\QueryBuilder\\:\\:setParameter\\(\\) expects string\\|null, int given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/QueryFilterHelper.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:conjunctionList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:format\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:formatAndList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:formatBulletList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:formatDefault\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:formatOrList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:formatOrderedList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:htmlList\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:removeEmptyValues\\(\\) has parameter \\$values with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenFormatter\\:\\:removeEmptyValues\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Helper/TokenFormatter.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldModel\\:\\:fetchCustomFieldsForObject\\(\\) should return array\\ but returns Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator&iterable\\\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldModel\\:\\:fetchEntities\\(\\) should return Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator&iterable\\ but returns array\\|Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldModel.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldOptionModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldValueModel\\:\\:buildItemsListData\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldValueModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldValueModel\\:\\:fetchItemsListData\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldValueModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldValueModel\\:\\:transformItemsListDataResult\\(\\) has parameter \\$result with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldValueModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomFieldValueModel\\:\\:transformItemsListDataResult\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomFieldValueModel.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomItemExportSchedulerModel.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomItemModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomItemModel\\:\\:getArrayTableData\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomItemModel.php + + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 12 + path: ../../plugins/CustomObjectsBundle/Model/CustomItemModel.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 12 + path: ../../plugins/CustomObjectsBundle/Model/CustomItemModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomObjectModel\\:\\:fetchAllPublishedEntities\\(\\) should return array\\ but returns Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator&iterable\\\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomObjectModel\\:\\:fetchEntities\\(\\) should return Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator&iterable\\ but returns array\\|Doctrine\\\\ORM\\\\Tools\\\\Pagination\\\\Paginator\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomObjectModel\\:\\:getMasterCustomObjects\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 4 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#" + count: 4 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomObjectModel\\:\\:\\$listModel is never read, only written\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Model/CustomObjectModel.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\CustomItemRouteProvider\\:\\:buildListRoute\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Provider/CustomItemRouteProvider.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:setValue\\(\\) has parameter \\$value with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Unsafe access to private constant MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:KEY_FILTER through static\\:\\:\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Unsafe access to private constant MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:KEY_LIMIT through static\\:\\:\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Unsafe access to private constant MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:KEY_ORDER_BY through static\\:\\:\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Unsafe access to private constant MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:KEY_ORDER_BY_DIR through static\\:\\:\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Unsafe access to private constant MauticPlugin\\\\CustomObjectsBundle\\\\Provider\\\\SessionProvider\\:\\:KEY_PAGE through static\\:\\:\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Provider/SessionProvider.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Report\\\\ReportColumnsBuilder\\:\\:getColumns\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Report/ReportColumnsBuilder.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Report\\\\ReportColumnsBuilder\\:\\:getJoinableColumns\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Report/ReportColumnsBuilder.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Report\\\\ReportColumnsBuilder\\:\\:\\$columnTypeMapping type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Report/ReportColumnsBuilder.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Report\\\\ReportColumnsBuilder\\:\\:\\$columns type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Report/ReportColumnsBuilder.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Repository\\\\CustomItemRepository\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Repository/CustomItemRepository.php + + - + message: "#^Call to method getId\\(\\) on an unknown class MauticPlugin\\\\CustomObjectsBundle\\\\Repository\\\\CustomField\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Repository/CustomObjectRepository.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Repository\\\\CustomObjectRepository\\:\\:getMasterObjectChoices\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Repository/CustomObjectRepository.php + + - + message: "#^PHPDoc tag @var for variable \\$customField contains unknown class MauticPlugin\\\\CustomObjectsBundle\\\\Repository\\\\CustomField\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Repository/CustomObjectRepository.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Security\\\\Permissions\\\\CustomObjectPermissions\\:\\:buildForm\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Security/Permissions/CustomObjectPermissions.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Security\\\\Permissions\\\\CustomObjectPermissions\\:\\:buildForm\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Security/Permissions/CustomObjectPermissions.php + + - + message: "#^Parameter \\#2 \\$level of method Mautic\\\\CoreBundle\\\\Security\\\\Permissions\\\\AbstractPermissions\\:\\:addExtendedFormFields\\(\\) expects string, int\\|null given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Security/Permissions/CustomObjectPermissions.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/CustomFieldFilterQueryBuilder.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/CustomItemNameFilterQueryBuilder.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/CustomObjectMergedFilterQueryBuilder.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/QueryFilterFactory.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\Filter\\\\QueryFilterFactory\\:\\:configureQueryBuilderFromSegmentFilter\\(\\) has parameter \\$segmentFilter with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/QueryFilterFactory.php + + - + message: "#^PHPDoc tag @throws with type MauticPlugin\\\\CustomObjectsBundle\\\\Exception\\\\InvalidSegmentFilterException\\|MauticPlugin\\\\CustomObjectsBundle\\\\Exception\\\\NotFoundException\\|MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\Filter\\\\Exception is not subtype of Throwable$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/Filter/QueryFilterFactory.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\UnionQueryContainer\\:\\:getParameterTypes\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/UnionQueryContainer.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\UnionQueryContainer\\:\\:getParameters\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/UnionQueryContainer.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\UnionQueryContainer\\:\\:\\$parameterTypes type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/UnionQueryContainer.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Segment\\\\Query\\\\UnionQueryContainer\\:\\:\\$parameters type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Segment/Query/UnionQueryContainer.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\AbstractApiPlatformFunctionalTest\\:\\:createEntity\\(\\) has parameter \\$payload with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\AbstractApiPlatformFunctionalTest\\:\\:requestEntity\\(\\) has parameter \\$payload with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\AbstractApiPlatformFunctionalTest\\:\\:setPermission\\(\\) has parameter \\$permissionArray with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\AbstractApiPlatformFunctionalTest\\:\\:updateEntity\\(\\) has parameter \\$payload with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\AbstractApiPlatformFunctionalTest\\:\\:\\$clientServer type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/AbstractApiPlatformFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getCRUDProvider\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getCRUDWithOptionsProvider\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getCreatePayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getCreateWithOptionsPayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getEditPayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:getEditWithOptionsPayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:runTestCustomFieldCRUD\\(\\) has parameter \\$permissions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:runTestCustomFieldWithOptionsCRUD\\(\\) has parameter \\$permissions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:runTestCustomFieldWithOptionsCRUD\\(\\) has parameter \\$retrievedOptions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldFunctionalTest\\:\\:runTestCustomFieldWithOptionsCRUD\\(\\) has parameter \\$updatedOptions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldOptionFunctionalTest\\:\\:getCRUDProvider\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldOptionFunctionalTest\\:\\:getCreatePayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldOptionFunctionalTest\\:\\:getEditPayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomFieldOptionFunctionalTest\\:\\:runTestCustomFieldOptionCRUD\\(\\) has parameter \\$permissions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomFieldOptionFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomObjectFunctionalTest\\:\\:getCRUDProvider\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomObjectFunctionalTest\\:\\:getCreatePayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomObjectFunctionalTest\\:\\:getEditPayload\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\ApiPlatform\\\\CustomObjectFunctionalTest\\:\\:runTestCustomObjectCRUD\\(\\) has parameter \\$permissions with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/ApiPlatform/CustomObjectFunctionalTest.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Controller/CustomItemListControllerShownFieldTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:testDeleteChildObject\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Call to an undefined method MauticPlugin\\\\CustomObjectsBundle\\\\Repository\\\\CustomObjectRepository\\:\\:findOneById\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Controller/CustomObjectFormTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\Controller\\\\CustomObjectFormTest\\:\\:assertCustomObject\\(\\) has parameter \\$expected with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Controller/CustomObjectFormTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\EventListener\\\\FilterOperatorSubscriberTest\\:\\:testIfNewOperatorNotInCustomObjectsAddedinSegmentFilter\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/EventListener/FilterOperatorSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\EventListener\\\\FilterOperatorSubscriberTest\\:\\:testIfProperContactsAreAddedinSegmentWithNotInCustomObjectsFilter\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/EventListener/FilterOperatorSubscriberTest.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/EventListener/ImportSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\Helper\\\\QueryFilterHelperTest\\:\\:assertMatchWhere\\(\\) has parameter \\$filter with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Helper/QueryFilterHelperTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\Segment\\\\Query\\\\Filter\\\\CustomFieldFilterQueryBuilderTest\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\Segment\\\\Query\\\\Filter\\\\CustomItemNameFilterQueryBuilderTest\\:\\:executeSelect\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^Call to an undefined method Mautic\\\\LeadBundle\\\\Entity\\\\LeadRepository\\:\\:findOneByEmail\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Functional/Segment/Query/Filter/CustomItemRelationQueryBuilderTestCase.php + + - + message: "#^Call to an undefined method Mautic\\\\CoreBundle\\\\Controller\\\\MauticController&Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\Controller\\:\\:setRequest\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Call to an undefined method Mautic\\\\CoreBundle\\\\Controller\\\\MauticController&Symfony\\\\Bundle\\\\FrameworkBundle\\\\Controller\\\\Controller\\:\\:setTranslator\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\ControllerTestCase\\:\\:\\$request has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\ControllerTestCase\\:\\:\\$requestStack has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\ControllerTestCase\\:\\:\\$router \\(Symfony\\\\Component\\\\Routing\\\\Router\\) does not accept PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Symfony\\\\Component\\\\Routing\\\\RouterInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\ControllerTestCase\\:\\:\\$session has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$fieldId with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$fieldType with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$mapExtras with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$objectId with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$panelCount with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestMock\\(\\) has parameter \\$panelId with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$customFieldFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$fieldRouteProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$formController has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$objectRouteProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$customFieldFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$fieldRouteProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$saveController has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\CancelControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/CancelControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\CancelControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/CancelControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\CancelControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/CancelControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Call to an undefined method Mautic\\\\CoreBundle\\\\Helper\\\\UserHelper\\:\\:expects\\(\\)\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/FormControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\FormControllerTest\\:\\:testEditActionWhenTheItemIsLocked\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/FormControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\FormControllerTest\\:\\:testEditWithRedirectToContactActionWhenTheItemIsLocked\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\FormControllerTest\\:\\:\\$form type has no value type specified in iterable type Symfony\\\\Component\\\\Form\\\\FormInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LinkControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LinkControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LinkControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LinkControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LinkControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LinkControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ListControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ListControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ListControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ListControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ListControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LookupControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LookupControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LookupControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LookupControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\LookupControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/LookupControllerTest.php + + - + message: "#^Call to an undefined method Mautic\\\\CoreBundle\\\\Helper\\\\UserHelper\\:\\:expects\\(\\)\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/SaveControllerTest.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Routing\\\\Router\\:\\:expects\\(\\)\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\SaveControllerTest\\:\\:\\$form type has no value type specified in iterable type Symfony\\\\Component\\\\Form\\\\FormInterface\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$auditLog has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$customItemXrefContactModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ViewControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomItem/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\CancelControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/CancelControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\CancelControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/CancelControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\CancelControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/CancelControllerTest.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:expects\\(\\)\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:\\$leadListIndex is never read, only written\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$customFieldTypeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$lockFlashMessageHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ListControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ListControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ListControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ListControllerTest\\:\\:\\$sessionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$customFieldTypeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$flashBag has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$lockFlashMessageHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$optionsToStringTransformer has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$paramsToStringTransformer has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\SaveControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$auditLog has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$formFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ViewControllerTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Controller/CustomObject/ViewControllerTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractCustomFieldTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractCustomFieldTypeTest\\:\\:\\$fieldType \\(MauticPlugin\\\\CustomObjectsBundle\\\\CustomFieldType\\\\EmailType\\) does not accept MauticPlugin\\\\CustomObjectsBundle\\\\CustomFieldType\\\\AbstractCustomFieldType&PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractCustomFieldTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractCustomFieldTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractCustomFieldTypeTest.php + + - + message: "#^Parameter \\#3 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\CustomFieldType\\\\AbstractMultivalueType\\:\\:createValueEntity\\(\\) expects null, array\\ given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractMultivalueTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractMultivalueTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractMultivalueTypeTest\\:\\:\\$provider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractMultivalueTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractMultivalueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractTextTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractTextTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractTextTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\AbstractTextTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/AbstractTextTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\CountryTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/CountryTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTimeTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTimeTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTimeTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTimeTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTimeTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTimeTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTimeTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTimeTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\DateTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/DateTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\EmailTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/EmailTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\EmailTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/EmailTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\IntTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/IntTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\IntTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/IntTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\IntTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/IntTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\IntTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/IntTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\MultiselectTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/MultiselectTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\PhoneTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/PhoneTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\PhoneTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/PhoneTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\SelectTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/SelectTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\SelectTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/SelectTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\SelectTypeTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/SelectTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\SelectTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/SelectTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\UrlTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/UrlTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\CustomFieldType\\\\UrlTypeTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/CustomFieldType/UrlTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\AbstractCustomFieldValueTest\\:\\:\\$abstractCFValue has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/AbstractCustomFieldValueTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\AbstractCustomFieldValueTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/AbstractCustomFieldValueTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\AbstractCustomFieldValueTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/AbstractCustomFieldValueTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\AbstractCustomFieldValueTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/AbstractCustomFieldValueTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomField\\\\ParamsTest\\:\\:testConstructorAndToArray\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomField/ParamsTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomField\\\\ParamsTest\\:\\:testGettersSetters\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomField/ParamsTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomField\\\\ParamsTest\\:\\:testToArrayRemovingFalseAndNullValues\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomField/ParamsTest.php + + - + message: "#^Parameter \\#1 \\$array \\(array\\{placeholder\\: null\\}\\) to function array_filter contains falsy values only, the result will always be an empty array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomField/ParamsTest.php + + - + message: "#^Unable to resolve the template type RealInstanceType in call to method PHPUnit\\\\Framework\\\\TestCase\\:\\:createMock\\(\\)$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldFactoryTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldOptionTest\\:\\:testArrayAccessor\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldOptionTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldOptionTest\\:\\:testConstructorAndToArray\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldOptionTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldOptionTest\\:\\:testGettersSetters\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldOptionTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldTest\\:\\:testCanHaveMultipleValuesForCheckboxType\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldTest\\:\\:testCanHaveMultipleValuesForDateType\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomFieldTest\\:\\:testDefaultValueTransformation\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomFieldTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Entity\\\\CustomObjectTest\\:\\:testGetCfByOrder\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Entity/CustomObjectTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ApiSubscriberTest\\:\\:\\$apiEntityEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ApiSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ApiSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ApiSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ApiSubscriberTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ApiSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ApiSubscriberTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ApiSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ApiSubscriberTest\\:\\:\\$request has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ApiSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$assetsHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$assetsSubscriber has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$getResponseEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$request has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$auditLogModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$auditLogSubscriber has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$customItemEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$customObjectEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AuditLogSubscriberTest\\:\\:\\$ipLookupHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/AuditLogSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$campaignBuilderEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$campaignExecutionEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$contact has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$queryFilterFactory has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$queryFilterHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$segmentQueryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$statement has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$leadEventLogRepo has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$leadTimelineEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$routeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactSubscriberTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ContactTabSubscriberTest\\:\\:testSubscriberEvents\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ContactTabSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomFieldPostLoadSubscriberTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomFieldPostLoadSubscriberTest\\:\\:\\$customFieldTypeProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomFieldPostLoadSubscriberTest\\:\\:\\$event has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomFieldPostLoadSubscriberTest\\:\\:\\$subscriber has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$contact has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$discoveryEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$event has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$listDbalEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$listEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$queryBuilderDbal has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$xref has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$customItemA has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$customItemB has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$discoveryEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$event has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$expr has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$listEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$xref has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$event has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$itemPermissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$itemRouteProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$objectPermissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$objectRouteProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomObjectButtonSubscriberTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/CustomObjectButtonSubscriberTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/FilterOperatorSubscriberTest.php + + - + message: "#^PHPDoc tag @var for variable \\$formMock has no value type specified in iterable type Symfony\\\\Component\\\\Form\\\\FormInterface\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/FilterOperatorSubscriberTest.php + + - + message: "#^Parameter \\#1 \\$form of class Mautic\\\\LeadBundle\\\\Event\\\\FormAdjustmentEvent constructor expects iterable\\&Symfony\\\\Component\\\\Form\\\\FormInterface, PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\|Symfony\\\\Component\\\\Form\\\\FormInterface given\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/FilterOperatorSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$customFieldRepository has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$customItemImportModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$form has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$import has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$importInitEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$importMappingEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$importProcessEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$importValidateEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$permissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ImportSubscriberTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ImportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\MenuSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/MenuSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\MenuSubscriberTest\\:\\:\\$customObjectModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/MenuSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\MenuSubscriberTest\\:\\:\\$menuEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/MenuSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ReportSubscriberTest\\:\\:getCustomObjectsCollection\\(\\) return type has no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ReportSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ReportSubscriberTest\\:\\:testThatIdDoesntProcessContextsWithEmptyOrNotIntCustomObjectsID\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ReportSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ReportSubscriberTest\\:\\:testThatIdDoesntProcessNotExistingCustomObjects\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ReportSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\ReportSubscriberTest\\:\\:testThatOnReportGenerateMethodDoesntProcessWrongContexts\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/ReportSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$configProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$customItemModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$customItemXrefContactRepository has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$objectEvent has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$request has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\SerializerSubscriberTest\\:\\:\\$requestStack has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/EventListener/SerializerSubscriberTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Exception\\\\InvalidCustomObjectFormatListExceptionTest\\:\\:testAll\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Exception/InvalidCustomObjectFormatListExceptionTest.php + + - + message: "#^Parameter \\#1 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:reverseTransform\\(\\) expects array\\, array\\\\>\\> given\\.$#" + count: 4 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:transform\\(\\) expects Doctrine\\\\ORM\\\\PersistentCollection&iterable\\, Doctrine\\\\Common\\\\Collections\\\\ArrayCollection\\<\\*NEVER\\*, \\*NEVER\\*\\> given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:transform\\(\\) expects Doctrine\\\\ORM\\\\PersistentCollection&iterable\\, Doctrine\\\\Common\\\\Collections\\\\ArrayCollection\\ given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^Parameter \\#1 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\OptionsTransformer\\:\\:transform\\(\\) expects Doctrine\\\\ORM\\\\PersistentCollection&iterable\\, null given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^Parameter \\#1 \\$params of method MauticPlugin\\\\CustomObjectsBundle\\\\Form\\\\DataTransformer\\\\ParamsToStringTransformer\\:\\:transform\\(\\) expects MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomField\\\\Params\\|null, array given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/DataTransformer/ParamsToStringTransformerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CampaignConditionFieldValueTypeTest\\:\\:testConfigureOptions\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CampaignConditionFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$customFieldType has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$customFieldValue has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$formBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomFieldValueTypeTest\\:\\:\\$optionsResolver has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomFieldValueTypeTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomObjectTypeTest\\:\\:buildForm\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomObjectTypeTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomObjectTypeTest\\:\\:testBuildFormExistingObject\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomObjectTypeTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomObjectTypeTest\\:\\:testBuildFormNewObject\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomObjectTypeTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Type\\\\CustomObjectTypeTest\\:\\:testConfigureOptions\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Type/CustomObjectTypeTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Validator\\\\CustomObjectTypeValuesTest\\:\\:testGetTargets\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Validator\\\\CustomObjectTypeValuesTest\\:\\:testValidatedBy\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesTest.php + + - + message: "#^Access to an undefined property PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\|Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$missingMasterObject\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Validator\\\\CustomObjectTypeValuesValidatorTest\\:\\:testValidateIgnoreCompletely\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Validator\\\\CustomObjectTypeValuesValidatorTest\\:\\:testValidateIgnoreMasterObject\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Form\\\\Validator\\\\CustomObjectTypeValuesValidatorTest\\:\\:testValidateNoCustomObject\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\CustomFieldQueryBuilder\\\\CalculatorTest\\:\\:assertMatrixEquals\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/CustomFieldQueryBuilder/CalculatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\CustomFieldQueryBuilder\\\\CalculatorTest\\:\\:assertMatrixEquals\\(\\) has parameter \\$expectedMatrix with no value type specified in iterable type array\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/CustomFieldQueryBuilder/CalculatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\CustomFieldQueryBuilder\\\\CalculatorTest\\:\\:getSuffix\\(\\) has parameter \\$decisionValue with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/CustomFieldQueryBuilder/CalculatorTest.php + + - + message: "#^Parameter \\#4 \\$value of method MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\QueryFilterHelper\\:\\:addCustomObjectNameExpression\\(\\) expects string\\|null, int given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/QueryFilterHelperTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:testAvailableFormats\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:testFormatManyValues\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:testFormatOneValue\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:testIsValidFormat\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:\\$availableFormats has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:\\$manyValues has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:\\$noValues has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\TokenFormatterTest\\:\\:\\$oneValue has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Helper/TokenFormatterTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldOptionModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldOptionModelTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldOptionModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldOptionModelTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldOptionModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldOptionModelTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldOptionModelTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 2 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$customFieldValueModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$filterOperatorProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$statement has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$validator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomFieldValueModelTest\\:\\:\\$violationList has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$customFieldValueModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$customItemPermissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$customItemRepository has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$dbalQueryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$dispatcher has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$statement has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$user has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$userHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$validator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$violationList has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemXrefContactModelTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemXrefContactModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemXrefContactModelTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemXrefContactModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemXrefContactModelTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemXrefContactModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemXrefContactModelTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemXrefContactModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemXrefContactModelTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomItemXrefContactModelTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:testGetMasterCustomObjects\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$customField has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$customFieldModel has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$customObjectPermissionProvider has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$customObjectRepository has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$databasePlatform has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$dispatcher has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$queryBuilderDbal has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$statement has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$translator has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$user has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$userHelper has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomFieldRouteProviderTest\\:\\:\\$router has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomFieldRouteProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemPermissionProviderTest\\:\\:\\$corePermissions has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemPermissionProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemPermissionProviderTest\\:\\:\\$customItem has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemPermissionProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemPermissionProviderTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemPermissionProviderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemRouteProviderTest\\:\\:testThatBuildContactViewRouteReturnsCorrectUrl\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemRouteProviderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemRouteProviderTest\\:\\:testThatBuildEditRouteWithRedirectToContactReturnsCorrectUrl\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemRouteProviderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemRouteProviderTest\\:\\:testThatBuildNewRouteWithRedirectToContactReturnsCorrectUrl\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemRouteProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomItemRouteProviderTest\\:\\:\\$router has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomItemRouteProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomObjectPermissionProviderTest\\:\\:\\$entity has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomObjectPermissionProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomObjectPermissionProviderTest\\:\\:\\$permissions has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomObjectPermissionProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Provider\\\\CustomObjectRouteProviderTest\\:\\:\\$router has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Provider/CustomObjectRouteProviderTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomFieldRepositoryTest\\:\\:\\$classMetadata has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomFieldRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomFieldRepositoryTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomFieldRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomFieldRepositoryTest\\:\\:\\$expression has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomFieldRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomFieldRepositoryTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomFieldRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomFieldRepositoryTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomFieldRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$contact has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$customObject has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$expr has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemRepositoryTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$classMetadata has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$connection has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$contact has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$entityManager has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$expr has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$expressionBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$query has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$queryBuilder has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$queryBuilderDbal has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Repository\\\\CustomItemXrefContactRepositoryTest\\:\\:\\$statement has no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Segment\\\\Query\\\\Filter\\\\CustomItemNameFilterQueryBuilderTest\\:\\:parameterValueProvider\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Segment\\\\Query\\\\Filter\\\\CustomItemNameFilterQueryBuilderTest\\:\\:testApplyQuery\\(\\) has parameter \\$parameterValue with no type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^PHPDoc tag @param has invalid value \\(\\$parameterValue\\)\\: Unexpected token \"\\$parameterValue\", expected type at offset 69$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 3 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/Filter/QueryFilterFactoryTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Segment\\\\Query\\\\UnionQueryContainerTest\\:\\:testParameterTypesCheck\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/UnionQueryContainerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Segment\\\\Query\\\\UnionQueryContainerTest\\:\\:testParametersCheck\\(\\) has no return type specified\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/UnionQueryContainerTest.php + + - + message: "#^Parameter \\#3 \\$type of method Mautic\\\\LeadBundle\\\\Segment\\\\Query\\\\QueryBuilder\\:\\:setParameter\\(\\) expects string\\|null, int given\\.$#" + count: 1 + path: ../../plugins/CustomObjectsBundle/Tests/Unit/Segment/Query/UnionQueryContainerTest.php + diff --git a/phpstan-baseline-php-versions.neon.php b/phpstan-baseline-php-versions.neon.php new file mode 100644 index 000000000..067bc2d19 --- /dev/null +++ b/phpstan-baseline-php-versions.neon.php @@ -0,0 +1,17 @@ += 70400 && PHP_VERSION_ID < 80000) { + $includes[] = __DIR__.'/phpstan-baseline-7.4.neon'; +} elseif (PHP_VERSION_ID >= 80000) { + $includes[] = __DIR__.'/phpstan-baseline-8.0.neon'; +} + +$config = []; +$config['includes'] = $includes; +$config['parameters']['phpVersion'] = PHP_VERSION_ID; + +return $config; diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 000000000..f0a54ab83 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,706 @@ +parameters: + ignoreErrors: + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Console\\\\Helper\\\\HelperInterface\\:\\:ask\\(\\)\\.$#" + count: 1 + path: Command/GenerateSampleDataCommand.php + + - + message: "#^Trait MauticPlugin\\\\CustomObjectsBundle\\\\CustomFieldType\\\\DateOperatorTrait is used zero times and is not analysed\\.$#" + count: 1 + path: CustomFieldType/DateOperatorTrait.php + + - + message: """ + #^Parameter \\$factory of method MauticPlugin\\\\CustomObjectsBundle\\\\CustomObjectsBundle\\:\\:installAllTablesIfMissing\\(\\) has typehint with deprecated class Mautic\\\\CoreBundle\\\\Factory\\\\MauticFactory\\: + 2\\.0 to be removed in 3\\.0$# + """ + count: 1 + path: CustomObjectsBundle.php + + - + message: """ + #^Call to deprecated method execute\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\QueryBuilder\\: + Use \\{@see executeQuery\\(\\)\\} or \\{@see executeStatement\\(\\)\\} instead\\.$# + """ + count: 1 + path: EventListener/CampaignSubscriber.php + + - + message: "#^Instanceof between int\\|string and Doctrine\\\\DBAL\\\\Driver\\\\Statement will always evaluate to false\\.$#" + count: 1 + path: EventListener/CampaignSubscriber.php + + - + message: """ + #^Parameter \\$event of method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CampaignSubscriber\\:\\:onCampaignTriggerAction\\(\\) has typehint with deprecated class Mautic\\\\CampaignBundle\\\\Event\\\\CampaignExecutionEvent\\: + 2\\.13\\.0; to be removed in 3\\.0$# + """ + count: 1 + path: EventListener/CampaignSubscriber.php + + - + message: """ + #^Parameter \\$event of method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CampaignSubscriber\\:\\:onCampaignTriggerCondition\\(\\) has typehint with deprecated class Mautic\\\\CampaignBundle\\\\Event\\\\CampaignExecutionEvent\\: + 2\\.13\\.0; to be removed in 3\\.0$# + """ + count: 1 + path: EventListener/CampaignSubscriber.php + + - + message: """ + #^Call to deprecated method execute\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\QueryBuilder\\: + Use \\{@see executeQuery\\(\\)\\} or \\{@see executeStatement\\(\\)\\} instead\\.$# + """ + count: 1 + path: EventListener/DynamicContentSubscriber.php + + - + message: "#^Instanceof between int\\|string and Doctrine\\\\DBAL\\\\Driver\\\\Statement will always evaluate to false\\.$#" + count: 1 + path: EventListener/DynamicContentSubscriber.php + + - + message: "#^Expression on left side of \\?\\? is not nullable\\.$#" + count: 1 + path: EventListener/ImportSubscriber.php + + - + message: "#^Instanceof between Doctrine\\\\Common\\\\Collections\\\\ArrayCollection and Doctrine\\\\Common\\\\Collections\\\\ArrayCollection will always evaluate to true\\.$#" + count: 1 + path: EventListener/ReportSubscriber.php + + - + message: "#^Instanceof between MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject and MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomObject will always evaluate to true\\.$#" + count: 1 + path: EventListener/ReportSubscriber.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\ReportSubscriber\\:\\:sortCustomObjects\\(\\) is unused\\.$#" + count: 1 + path: EventListener/ReportSubscriber.php + + - + message: """ + #^Call to deprecated method execute\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\QueryBuilder\\: + Use \\{@see executeQuery\\(\\)\\} or \\{@see executeStatement\\(\\)\\} instead\\.$# + """ + count: 1 + path: EventListener/SegmentFiltersDictionarySubscriber.php + + - + message: "#^Instanceof between int\\|string and Doctrine\\\\DBAL\\\\Driver\\\\Statement will always evaluate to false\\.$#" + count: 1 + path: EventListener/SegmentFiltersDictionarySubscriber.php + + - + message: "#^Instanceof between Mautic\\\\LeadBundle\\\\Entity\\\\Lead and Mautic\\\\LeadBundle\\\\Entity\\\\Lead will always evaluate to true\\.$#" + count: 1 + path: EventListener/SerializerSubscriber.php + + - + message: "#^Instanceof between MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomField\\\\Params and MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomField\\\\Params will always evaluate to true\\.$#" + count: 1 + path: Form/DataTransformer/ParamsToStringTransformer.php + + - + message: """ + #^Call to deprecated method add\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\Expression\\\\CompositeExpression\\: + This class will be made immutable\\. Use with\\(\\) instead\\.$# + """ + count: 2 + path: Helper/QueryFilterHelper.php + + - + message: """ + #^Call to deprecated method execute\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\QueryBuilder\\: + Use \\{@see executeQuery\\(\\)\\} or \\{@see executeStatement\\(\\)\\} instead\\.$# + """ + count: 1 + path: Helper/QueryFilterHelper.php + + - + message: """ + #^Call to deprecated method orX\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\Expression\\\\ExpressionBuilder\\: + Use `or\\(\\)` instead\\.$# + """ + count: 2 + path: Helper/QueryFilterHelper.php + + - + message: "#^Instanceof between int\\|string and Doctrine\\\\DBAL\\\\Driver\\\\Statement will always evaluate to false\\.$#" + count: 1 + path: Helper/QueryFilterHelper.php + + - + message: """ + #^Call to deprecated method hasPrimaryKey\\(\\) of class Doctrine\\\\DBAL\\\\Schema\\\\Table\\: + Use \\{@see getPrimaryKey\\(\\)\\} instead\\.$# + """ + count: 1 + path: Migrations/Version_0_0_12.php + + - + message: """ + #^Call to deprecated method execute\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\QueryBuilder\\: + Use \\{@see executeQuery\\(\\)\\} or \\{@see executeStatement\\(\\)\\} instead\\.$# + """ + count: 1 + path: Model/CustomFieldOptionModel.php + + - + message: """ + #^Call to deprecated method merge\\(\\) of class Doctrine\\\\ORM\\\\EntityManager\\: + 2\\.7 This method is being removed from the ORM and won't have any replacement$# + """ + count: 1 + path: Model/CustomFieldValueModel.php + + - + message: """ + #^Fetching deprecated class constant PARAM_INT_ARRAY of class Doctrine\\\\DBAL\\\\Connection\\: + Use \\{@see ArrayParameterType\\:\\:INTEGER\\} instead\\.$# + """ + count: 2 + path: Model/CustomFieldValueModel.php + + - + message: "#^Parameter \\#2 \\$contactIds of method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomItemImportModel\\:\\:linkContacts\\(\\) expects array\\, array\\ given\\.$#" + count: 1 + path: Model/CustomItemImportModel.php + + - + message: """ + #^Call to deprecated method execute\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\QueryBuilder\\: + Use \\{@see executeQuery\\(\\)\\} or \\{@see executeStatement\\(\\)\\} instead\\.$# + """ + count: 1 + path: Model/CustomItemModel.php + + - + message: """ + #^Call to deprecated method getConnection\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\QueryBuilder\\: + Use the connection used to instantiate the builder instead\\.$# + """ + count: 1 + path: Report/ReportColumnsBuilder.php + + - + message: "#^Call to function is_callable\\(\\) with callable\\(\\)\\: mixed will always evaluate to true\\.$#" + count: 1 + path: Report/ReportColumnsBuilder.php + + - + message: """ + #^Call to deprecated method execute\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\QueryBuilder\\: + Use \\{@see executeQuery\\(\\)\\} or \\{@see executeStatement\\(\\)\\} instead\\.$# + """ + count: 1 + path: Repository/CustomItemRepository.php + + - + message: "#^Instanceof between int\\|string and Doctrine\\\\DBAL\\\\Driver\\\\Statement will always evaluate to false\\.$#" + count: 1 + path: Repository/CustomItemRepository.php + + - + message: "#^PHPDoc tag @throws with type Doctrine\\\\DBAL\\\\DBALException is not subtype of Throwable$#" + count: 1 + path: Segment/Query/Filter/CustomFieldFilterQueryBuilder.php + + - + message: "#^PHPDoc tag @throws with type Doctrine\\\\DBAL\\\\DBALException is not subtype of Throwable$#" + count: 1 + path: Segment/Query/Filter/CustomItemNameFilterQueryBuilder.php + + - + message: "#^PHPDoc tag @throws with type Doctrine\\\\DBAL\\\\DBALException is not subtype of Throwable$#" + count: 1 + path: Segment/Query/UnionQueryContainer.php + + - + message: "#^You should use assertCount\\(\\$expectedCount, \\$variable\\) instead of assertSame\\(\\$expectedCount, \\$variable\\-\\>count\\(\\)\\)\\.$#" + count: 2 + path: Tests/Functional/Controller/CustomItemListControllerSearchTest.php + + - + message: "#^You should use assertCount\\(\\$expectedCount, \\$variable\\) instead of assertSame\\(\\$expectedCount, \\$variable\\-\\>count\\(\\)\\)\\.$#" + count: 3 + path: Tests/Functional/Controller/CustomItemListControllerShownFieldTest.php + + - + message: "#^You should use assertCount\\(\\$expectedCount, \\$variable\\) instead of assertSame\\(\\$expectedCount, \\$variable\\-\\>count\\(\\)\\)\\.$#" + count: 2 + path: Tests/Functional/Controller/CustomItemListControllerXrefTest.php + + - + message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertIsArray\\(\\) with array will always evaluate to true\\.$#" + count: 1 + path: Tests/Functional/Controller/CustomItemLookupControllerTest.php + + - + message: "#^You should use assertNull\\(\\) instead of assertSame\\(null, \\$actual\\)\\.$#" + count: 3 + path: Tests/Functional/EventListener/ApiSubscriberTest.php + + - + message: """ + #^Instantiation of deprecated class Mautic\\\\CampaignBundle\\\\Event\\\\CampaignExecutionEvent\\: + 2\\.13\\.0; to be removed in 3\\.0$# + """ + count: 1 + path: Tests/Functional/EventListener/CampaignSubscriberTest.php + + - + message: """ + #^Return type of method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\EventListener\\\\CampaignSubscriberTest\\:\\:createCampaignExecutionEvent\\(\\) has typehint with deprecated class Mautic\\\\CampaignBundle\\\\Event\\\\CampaignExecutionEvent\\: + 2\\.13\\.0; to be removed in 3\\.0$# + """ + count: 1 + path: Tests/Functional/EventListener/CampaignSubscriberTest.php + + - + message: "#^You should use assertCount\\(\\$expectedCount, \\$variable\\) instead of assertSame\\(\\$expectedCount, \\$variable\\-\\>count\\(\\)\\)\\.$#" + count: 4 + path: Tests/Functional/EventListener/ImportSubscriberTest.php + + - + message: "#^Call to function is_string\\(\\) with string will always evaluate to true\\.$#" + count: 1 + path: Tests/Functional/EventListener/SegmentFiltersDictionarySubscriberTest.php + + - + message: "#^Call to function is_string\\(\\) with string will always evaluate to true\\.$#" + count: 1 + path: Tests/Functional/Helper/QueryFilterHelperTest.php + + - + message: """ + #^Call to deprecated method execute\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\QueryBuilder\\: + Use \\{@see executeQuery\\(\\)\\} or \\{@see executeStatement\\(\\)\\} instead\\.$# + """ + count: 1 + path: Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php + + - + message: "#^Call to function is_string\\(\\) with string will always evaluate to true\\.$#" + count: 1 + path: Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php + + - + message: "#^Instanceof between int\\|string and Doctrine\\\\DBAL\\\\Driver\\\\Statement will always evaluate to false\\.$#" + count: 1 + path: Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php + + - + message: "#^PHPDoc tag @var with type Mautic\\\\LeadBundle\\\\Segment\\\\ContactSegmentFilter is not subtype of native type PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\.$#" + count: 2 + path: Tests/Functional/Segment/Query/Filter/CustomFieldFilterQueryBuilderTest.php + + - + message: """ + #^Call to deprecated method execute\\(\\) of class Doctrine\\\\DBAL\\\\Query\\\\QueryBuilder\\: + Use \\{@see executeQuery\\(\\)\\} or \\{@see executeStatement\\(\\)\\} instead\\.$# + """ + count: 1 + path: Tests/Functional/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^Call to function is_string\\(\\) with string will always evaluate to true\\.$#" + count: 1 + path: Tests/Functional/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^Instanceof between int\\|string and Doctrine\\\\DBAL\\\\Driver\\\\Statement will always evaluate to false\\.$#" + count: 1 + path: Tests/Functional/Segment/Query/Filter/CustomItemNameFilterQueryBuilderTest.php + + - + message: "#^Call to an undefined method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Functional\\\\Segment\\\\Query\\\\Filter\\\\CustomItemRelationQueryBuilderTest\\:\\:runCommand\\(\\)\\.$#" + count: 3 + path: Tests/Functional/Segment/Query/Filter/CustomItemRelationQueryBuilderTest.php + + - + message: "#^Call to function is_string\\(\\) with string will always evaluate to true\\.$#" + count: 1 + path: Tests/Functional/Segment/Query/Filter/CustomItemRelationQueryBuilderTest.php + + - + message: "#^Call to function is_string\\(\\) with string will always evaluate to true\\.$#" + count: 1 + path: Tests/Functional/Segment/Query/Filter/CustomObjectMergedFilterQueryBuilderTest.php + + - + message: "#^Call to function method_exists\\(\\) with 'Mautic\\\\\\\\LeadBundle\\\\\\\\Segment\\\\\\\\ContactSegmentFilterCrate' and 'getMergedProperty' will always evaluate to true\\.$#" + count: 1 + path: Tests/Functional/Segment/Query/Filter/NegativeOperatorFilterQueryBuilderTest.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\DependencyInjection\\\\ContainerInterface\\:\\:method\\(\\)\\.$#" + count: 2 + path: Tests/Unit/Controller/ControllerTestCase.php + + - + message: """ + #^Fetching class constant class of deprecated class Mautic\\\\CoreBundle\\\\Factory\\\\MauticFactory\\: + 2\\.0 to be removed in 3\\.0$# + """ + count: 1 + path: Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\ControllerTestCase\\:\\:\\$modelFactory \\(Mautic\\\\CoreBundle\\\\Factory\\\\ModelFactory&PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\) in empty\\(\\) is not falsy\\.$#" + count: 1 + path: Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\ControllerTestCase\\:\\:\\$requestStack \\(PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Symfony\\\\Component\\\\HttpFoundation\\\\RequestStack\\) in empty\\(\\) is not falsy\\.$#" + count: 1 + path: Tests/Unit/Controller/ControllerTestCase.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestStackMock\\(\\) has parameter \\$fieldId with no type specified\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestStackMock\\(\\) has parameter \\$fieldType with no type specified\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestStackMock\\(\\) has parameter \\$mapExtras with no value type specified in iterable type array\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestStackMock\\(\\) has parameter \\$objectId with no type specified\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestStackMock\\(\\) has parameter \\$panelCount with no type specified\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\AbstractFieldControllerTest\\:\\:createRequestStackMock\\(\\) has parameter \\$panelId with no type specified\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Property Symfony\\\\Component\\\\HttpFoundation\\\\Request\\:\\:\\$query \\(Symfony\\\\Component\\\\HttpFoundation\\\\InputBag\\\\) does not accept PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Symfony\\\\Component\\\\HttpFoundation\\\\ParameterBag\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Property Symfony\\\\Component\\\\HttpFoundation\\\\Request\\:\\:\\$request \\(Symfony\\\\Component\\\\HttpFoundation\\\\InputBag\\\\) does not accept PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Symfony\\\\Component\\\\HttpFoundation\\\\ParameterBag\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/AbstractFieldControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$formController \\(MauticPlugin\\\\CustomObjectsBundle\\\\Controller\\\\CustomField\\\\FormController&PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\) does not accept MauticPlugin\\\\CustomObjectsBundle\\\\Controller\\\\CustomField\\\\FormController\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\FormControllerTest\\:\\:\\$requestStack \\(PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Symfony\\\\Component\\\\HttpFoundation\\\\RequestStack\\) does not accept Symfony\\\\Component\\\\HttpFoundation\\\\RequestStack\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/FormControllerTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomField\\\\SaveControllerTest\\:\\:createSaveController\\(\\) has parameter \\$mapExtras with no value type specified in iterable type array\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\ControllerTestCase\\:\\:\\$requestStack \\(PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Symfony\\\\Component\\\\HttpFoundation\\\\RequestStack\\) does not accept Symfony\\\\Component\\\\HttpFoundation\\\\RequestStack\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomField/SaveControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$model has no type specified\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\BatchDeleteControllerTest\\:\\:\\$sessionProviderFactory has no type specified\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomItem/BatchDeleteControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\CancelControllerTest\\:\\:\\$sessionProviderFactory has no type specified\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomItem/CancelControllerTest.php + + - + message: "#^Access to an undefined property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$model\\.$#" + count: 2 + path: Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Access to an undefined property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\DeleteControllerTest\\:\\:\\$sessionProviderFactory\\.$#" + count: 5 + path: Tests/Unit/Controller/CustomItem/DeleteControllerTest.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertNotNull\\(\\) with list\\ and 'Custom Item Export…' will always evaluate to true\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomItem/ExportControllerTest.php + + - + message: "#^Access to an undefined property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\FormControllerTest\\:\\:\\$model\\.$#" + count: 9 + path: Tests/Unit/Controller/CustomItem/FormControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomItem\\\\ListControllerTest\\:\\:\\$sessionProviderFactory has no type specified\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomItem/ListControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\CancelControllerTest\\:\\:\\$sessionProviderFactory has no type specified\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomObject/CancelControllerTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\DeleteControllerTest\\:\\:\\$sessionProviderFactory has no type specified\\.$#" + count: 1 + path: Tests/Unit/Controller/CustomObject/DeleteControllerTest.php + + - + message: "#^Access to an undefined property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\FormControllerTest\\:\\:\\$model\\.$#" + count: 7 + path: Tests/Unit/Controller/CustomObject/FormControllerTest.php + + - + message: "#^Access to an undefined property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Controller\\\\CustomObject\\\\ListControllerTest\\:\\:\\$sessionProviderFactory\\.$#" + count: 5 + path: Tests/Unit/Controller/CustomObject/ListControllerTest.php + + - + message: "#^You should use assertNull\\(\\) instead of assertSame\\(null, \\$actual\\)\\.$#" + count: 1 + path: Tests/Unit/CustomFieldType/DateTimeTypeTest.php + + - + message: "#^You should use assertNull\\(\\) instead of assertSame\\(null, \\$actual\\)\\.$#" + count: 1 + path: Tests/Unit/CustomFieldType/DateTypeTest.php + + - + message: "#^Unable to resolve the template type T in call to method PHPUnit\\\\Framework\\\\TestCase\\:\\:createMock\\(\\)$#" + count: 1 + path: Tests/Unit/Entity/CustomFieldFactoryTest.php + + - + message: "#^Parameter \\#1 \\$expected of method PHPUnit\\\\Framework\\\\Assert\\:\\:assertSame\\(\\) contains unresolvable type\\.$#" + count: 1 + path: Tests/Unit/Entity/CustomFieldValueOptionTest.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertSame\\(\\) with Doctrine\\\\Common\\\\Collections\\\\ArrayCollection\\<\\*NEVER\\*, \\*NEVER\\*\\> and Doctrine\\\\Common\\\\Collections\\\\Collection&iterable\\ will always evaluate to false\\.$#" + count: 1 + path: Tests/Unit/Entity/CustomObjectTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$coreParametersHelper has no type specified\\.$#" + count: 1 + path: Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$packages has no type specified\\.$#" + count: 1 + path: Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\AssetsSubscriberTest\\:\\:\\$requestEvent has no type specified\\.$#" + count: 1 + path: Tests/Unit/EventListener/AssetsSubscriberTest.php + + - + message: """ + #^Fetching class constant class of deprecated class Mautic\\\\CampaignBundle\\\\Event\\\\CampaignExecutionEvent\\: + 2\\.13\\.0; to be removed in 3\\.0$# + """ + count: 1 + path: Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$result has no type specified\\.$#" + count: 1 + path: Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CampaignSubscriberTest\\:\\:\\$statement is never read, only written\\.$#" + count: 1 + path: Tests/Unit/EventListener/CampaignSubscriberTest.php + + - + message: """ + #^Fetching class constant class of deprecated class Doctrine\\\\ORM\\\\Event\\\\LifecycleEventArgs\\: + This class will be removed in ORM 3\\.0\\. Use one of the dedicated classes instead\\.$# + """ + count: 1 + path: Tests/Unit/EventListener/CustomFieldPostLoadSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefContactSubscriberTest\\:\\:\\$xrefSubscriber \\(MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CustomItemXrefContactSubscriber&PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\) does not accept MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CustomItemXrefContactSubscriber\\.$#" + count: 1 + path: Tests/Unit/EventListener/CustomItemXrefContactSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\CustomItemXrefCustomItemSubscriberTest\\:\\:\\$xrefSubscriber \\(MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CustomItemXrefCustomItemSubscriber&PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\) does not accept MauticPlugin\\\\CustomObjectsBundle\\\\EventListener\\\\CustomItemXrefCustomItemSubscriber\\.$#" + count: 1 + path: Tests/Unit/EventListener/CustomItemXrefCustomItemSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\DynamicContentSubscriberTest\\:\\:\\$statementMock is never read, only written\\.$#" + count: 1 + path: Tests/Unit/EventListener/DynamicContentSubscriberTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\EventListener\\\\TokenSubscriberTest\\:\\:\\$tokenParser \\(MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenParser&PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\) does not accept MauticPlugin\\\\CustomObjectsBundle\\\\Helper\\\\TokenParser\\.$#" + count: 1 + path: Tests/Unit/EventListener/TokenSubscriberTest.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) with 'Doctrine\\\\\\\\Common\\\\\\\\Collections\\\\\\\\ArrayCollection' and Doctrine\\\\Common\\\\Collections\\\\ArrayCollection&iterable\\ will always evaluate to true\\.$#" + count: 3 + path: Tests/Unit/Form/DataTransformer/OptionsToStringTransformerTest.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) with 'Doctrine\\\\\\\\Common\\\\\\\\Collections\\\\\\\\ArrayCollection' and Doctrine\\\\Common\\\\Collections\\\\ArrayCollection will always evaluate to true\\.$#" + count: 4 + path: Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertSame\\(\\) with array\\{list\\: array\\{11, 221\\}\\} and array\\ will always evaluate to false\\.$#" + count: 1 + path: Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertSame\\(\\) with array\\{list\\: array\\{\\}\\} and array\\ will always evaluate to false\\.$#" + count: 2 + path: Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^You should use assertCount\\(\\$expectedCount, \\$variable\\) instead of assertSame\\(\\$expectedCount, \\$variable\\-\\>count\\(\\)\\)\\.$#" + count: 3 + path: Tests/Unit/Form/DataTransformer/OptionsTransformerTest.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) with 'MauticPlugin\\\\\\\\CustomObjectsBundle\\\\\\\\Entity\\\\\\\\CustomField\\\\\\\\Params' and MauticPlugin\\\\CustomObjectsBundle\\\\Entity\\\\CustomField\\\\Params will always evaluate to true\\.$#" + count: 1 + path: Tests/Unit/Form/DataTransformer/ParamsToStringTransformerTest.php + + - + message: "#^Access to an undefined property PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$message\\.$#" + count: 1 + path: Tests/Unit/Form/Validator/AllowUniqueIdentifierValidatorTest.php + + - + message: "#^Access to an undefined property PHPUnit\\\\Framework\\\\MockObject\\\\MockObject&Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$missingMasterObject\\.$#" + count: 1 + path: Tests/Unit/Form/Validator/CustomObjectTypeValuesValidatorTest.php + + - + message: "#^Method MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Helper\\\\CustomFieldQueryBuilder\\\\CalculatorTest\\:\\:getSuffix\\(\\) is unused\\.$#" + count: 1 + path: Tests/Unit/Helper/CustomFieldQueryBuilder/CalculatorTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: Tests/Unit/Helper/QueryFilterFactoryTest.php + + - + message: """ + #^Call to deprecated method setMethods\\(\\) of class PHPUnit\\\\Framework\\\\MockObject\\\\MockBuilder\\: + https\\://github\\.com/sebastianbergmann/phpunit/pull/3687$# + """ + count: 1 + path: Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^You should use assertCount\\(\\$expectedCount, \\$variable\\) instead of assertSame\\(\\$expectedCount, \\$variable\\-\\>count\\(\\)\\)\\.$#" + count: 1 + path: Tests/Unit/Model/CustomFieldValueModelTest.php + + - + message: "#^Call to an undefined method MauticPlugin\\\\CustomObjectsBundle\\\\Model\\\\CustomItemImportModel\\:\\:setTranslator\\(\\)\\.$#" + count: 1 + path: Tests/Unit/Model/CustomItemImportModelTest.php + + - + message: "#^Call to an undefined method Mautic\\\\CoreBundle\\\\Twig\\\\Helper\\\\FormatterHelper\\:\\:expects\\(\\)\\.$#" + count: 1 + path: Tests/Unit/Model/CustomItemImportModelTest.php + + - + message: "#^Call to method expects\\(\\) on an unknown class MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\TranslatorInterface\\.$#" + count: 1 + path: Tests/Unit/Model/CustomItemImportModelTest.php + + - + message: "#^Class MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\TranslatorInterface not found\\.$#" + count: 1 + path: Tests/Unit/Model/CustomItemImportModelTest.php + + - + message: "#^Trying to mock an undefined method exists\\(\\) on class Mautic\\\\LeadBundle\\\\Entity\\\\LeadRepository\\.$#" + count: 3 + path: Tests/Unit/Model/CustomItemImportModelTest.php + + - + message: "#^Trying to mock an undefined method trans\\(\\) on class MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\TranslatorInterface\\.$#" + count: 1 + path: Tests/Unit/Model/CustomItemImportModelTest.php + + - + message: "#^You should use assertFalse\\(\\) instead of assertSame\\(\\) when expecting \"false\"$#" + count: 1 + path: Tests/Unit/Model/CustomItemImportModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomItemModelTest\\:\\:\\$statement is never read, only written\\.$#" + count: 1 + path: Tests/Unit/Model/CustomItemModelTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Model\\\\CustomObjectModelTest\\:\\:\\$listModel is never read, only written\\.$#" + count: 1 + path: Tests/Unit/Model/CustomObjectModelTest.php + + - + message: "#^You should use assertCount\\(\\$expectedCount, \\$variable\\) instead of assertSame\\(\\$expectedCount, count\\(\\$variable\\)\\)\\.$#" + count: 1 + path: Tests/Unit/Provider/CustomFieldTypeProviderTest.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertSame\\(\\) with array\\{'some items here'\\} and array\\ will always evaluate to false\\.$#" + count: 1 + path: Tests/Unit/Repository/CustomItemXrefContactRepositoryTest.php + + - + message: "#^Property MauticPlugin\\\\CustomObjectsBundle\\\\Tests\\\\Unit\\\\Security\\\\Permissions\\\\CustomObjectPermissionsTest\\:\\:\\$permissions \\(MauticPlugin\\\\CustomObjectsBundle\\\\Security\\\\Permissions\\\\CustomObjectPermissions&PHPUnit\\\\Framework\\\\MockObject\\\\MockObject\\) does not accept MauticPlugin\\\\CustomObjectsBundle\\\\Security\\\\Permissions\\\\CustomObjectPermissions\\.$#" + count: 1 + path: Tests/Unit/Security/Permissions/CustomObjectPermissionsTest.php + + - + message: "#^Call to method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) with 'Mautic\\\\\\\\LeadBundle\\\\\\\\Segment\\\\\\\\Query\\\\\\\\QueryBuilder' and Mautic\\\\LeadBundle\\\\Segment\\\\Query\\\\QueryBuilder will always evaluate to true\\.$#" + count: 1 + path: Tests/Unit/Segment/Query/UnionQueryContainerTest.php + + - + message: "#^Constant MAUTIC_TABLE_PREFIX not found\\.$#" + count: 1 + path: Helper/ContactFilterMatcher.php + + - + message: """ + #^Fetching deprecated class constant PARAM_INT_ARRAY of class Doctrine\\\\DBAL\\\\Connection\\: + Use \\{@see ArrayParameterType\\:\\:INTEGER\\} instead\\.$# + """ + count: 2 + path: Tests/Unit/Segment/Query/UnionQueryContainerTest.php diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 000000000..3eb4949c0 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,28 @@ +includes: + - phpstan-baseline-php-versions.neon.php + - phpstan-baseline.neon + - ../../vendor/phpstan/phpstan/conf/bleedingEdge.neon + +parameters: + level: 6 + reportUnmatchedIgnoredErrors: false + checkGenericClassInNonGenericObjectType: false + parallel: + maximumNumberOfProcesses: 4 + processTimeout: 1000.0 + scanDirectories: + - ../../app + paths: + - . + excludePaths: + - CustomFieldType/*Type.php # This should be refactored + - *.html.php # this can be removed in Mautic 5 + - Extension/CustomItemListeningExtension.php # PHPSTAN is confused because it exists only if API Platform does. + - Serializer/ApiNormalizer.php # PHPSTAN is confused because it exists only if API Platform does. + - Tests/Unit/Serializer/ApiNormalizerTest.php # PHPSTAN is confused because it exists only if API Platform does. + - DataPersister/CustomItemDataPersister.php # PHPSTAN is confused because it exists only if API Platform does. + - Tests/Unit/EventListener/SegmentFiltersChoicesGenerateSubscriberTest.php + dynamicConstantNames: + - MAUTIC_ENV + - MAUTIC_TABLE_PREFIX + - MAUTIC_VERSION diff --git a/phpunit.xml b/phpunit.xml index 874d2f418..9d223d1ac 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -22,10 +22,13 @@ - - - - + + + + + + +