Search code examples
phpsymfonyshopwareshopware6

Shopware 6 Plugin: How can I check wildcard emails against a blacklist


I have developed a Shopware 6 plugin that checks if an email is in a blacklist before allowing reviews. It works but currently does a database query for every email being checked. If I am in a scheduled task run that sends out 50 emails and I have 1000 entries with wildcard entries, this code won't work anymore.

I would like to optimize the plugin to:

  • Support wildcard patterns in the blacklist (e.g. *@amazon.com)
  • Fetch the blacklist once and loop through it instead of separate queries

Here is the current code:

use Monolog\Logger;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Swa\ProductReviews\Components\LoggerHelper;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;


class MailWithBlacklist {
    private EntityRepository $blacklistRepository;
    protected LoggerHelper $loggerHelper;
    
    public function __construct(EntityRepository $blacklistRepository, LoggerHelper $loggerHelper) {
        $this->blacklistRepository = $blacklistRepository;
        $this->loggerHelper = $loggerHelper;
    }
    
    /**
     * 
     * @param string $email
     * @param Context $context
     * @return bool
     */
    public function isEmailBlacklisted(string $email, Context $context): bool
    {

        $criteria = new Criteria();
        $criteria->addFilter(new EqualsFilter('email', $email));

        
        $blacklistEntry = $this->blacklistRepository->search($criteria, $context)->first();

        $this->loggerHelper->addDirectRecord(Logger::DEBUG, 'end of isEmailBlacklisted' , ['blacklistEntry' => $blacklistEntry]);
        return $blacklistEntry !== null;
    }
}

How can I modify this code?

Any help is appreciated.


Solution

  • To extend the plugin for wildcards and fetch the blacklist once, you can follow these steps:

    • Fetch the blacklist entries once and initialize $blacklistCache.
    • Loop through the $blacklistCache and use a helper method matchesWildcard to check for wildcard matches.
    • Add a helper method matchesWildcard to check the email against the wildcard pattern using preg_match method.
    class MailWithBlacklist {
        private $blacklistCache;
        private EntityRepository $blacklistRepository;
        protected LoggerHelper $loggerHelper;
        
        public function __construct(EntityRepository $blacklistRepository, LoggerHelper $loggerHelper) {
            $this->blacklistRepository = $blacklistRepository;
            $this->loggerHelper = $loggerHelper;
        }
        
        /**
         * 
         * @param string $email
         * @param Context $context
         * @return bool
         */
        public function isEmailBlacklisted(string $email, Context $context): bool
        {
         
            $criteria = new Criteria();
            $this->blacklistCache = $this->blacklistRepository->search($criteria, $context)->getEntities();
         
            foreach ($this->blacklistCache as $entry) {
             
                if ($this->matchesWildcard($email, $entry->getEmail())) {
     
                    return true;
                }
            }
            
            return false;
        }
        
        private function matchesWildcard(string $email, string $pattern): bool
        {
            $pattern = preg_quote($pattern, '/');
     
            $pattern = str_replace('\*', '.*', $pattern);
            
            return (bool) preg_match("/$pattern/i", $email);
        }
    }