HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/be.naniguide.com/app/Model/Blacklist.php
<?php

/**
 * Blacklist class.
 *
 * Model for blacklisted email addresses
 *
 * LICENSE: This product includes software developed at
 * the Acelle Co., Ltd. (http://acellemail.com/).
 *
 * @category   MVC Model
 *
 * @author     N. Pham <[email protected]>
 * @author     L. Pham <[email protected]>
 * @copyright  Acelle Co., Ltd
 * @license    Acelle Co., Ltd
 *
 * @version    1.0
 *
 * @link       http://acellemail.com
 */

namespace Acelle\Model;

use Illuminate\Database\Eloquent\Model;
use Acelle\Library\Tool;
use Acelle\Library\StringHelper;
use DB;

use function Acelle\Helpers\read_csv;

class Blacklist extends Model
{
    protected $connection = 'mysql';

    public const IMPORT_TEMP_DIR = 'app/tmp';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'email', 'reason',
    ];

    /**
     * Get all items.
     *
     * @return collect
     */
    public static function getAll()
    {
        return self::select('blacklists.*');
    }

    public function scopeGlobal($query)
    {
        return $query->whereNull('customer_id');
    }

    /**
     * Get all items.
     *
     * @return collect
     */
    public function delist($customer = null)
    {
        if (is_null($customer)) {
            $sql = sprintf('UPDATE %s SET status = %s WHERE status = %s AND email = %s', table('subscribers'), db_quote(Subscriber::STATUS_SUBSCRIBED), db_quote(Subscriber::STATUS_BLACKLISTED), db_quote($this->email));
        } else {
            // slow: $sql = sprintf('UPDATE %s SET status = %s WHERE status = %s AND email = %s AND mail_list_id IN (SELECT id FROM %s WHERE customer_id = %s)', table('subscribers'), db_quote(Subscriber::STATUS_SUBSCRIBED), db_quote(Subscriber::STATUS_BLACKLISTED), db_quote($this->email), table('mail_lists'), $customer->id);
            $sql = sprintf('UPDATE %s s INNER JOIN %s m ON m.id = s.mail_list_id SET s.status = %s WHERE s.status = %s AND s.email = %s AND m.customer_id = %s', table('subscribers'), table('mail_lists'), db_quote(Subscriber::STATUS_SUBSCRIBED), db_quote(Subscriber::STATUS_BLACKLISTED), db_quote($this->email), $customer->id);
        }
        \DB::statement($sql);
    }

    /**
     * Blacklist all subscribers of the same email address.
     *
     * @return collect
     */
    public static function doBlacklist($customer = null)
    {
        if (Setting::isYes('blacklist.use_global_blacklist')) {
            $sql = sprintf('UPDATE %s s INNER JOIN %s b ON b.email = s.email SET status = %s WHERE s.status = %s AND b.customer_id IS NULL', table('subscribers'), table('blacklists'), db_quote(Subscriber::STATUS_BLACKLISTED), db_quote(Subscriber::STATUS_SUBSCRIBED));
            \DB::statement($sql);
        }

        // user wide blacklist
        if (!is_null($customer)) {
            $sql = sprintf('UPDATE %s s INNER JOIN %s b ON b.email = s.email INNER JOIN %s m ON m.id = s.mail_list_id SET s.status = %s WHERE s.status = %s AND m.customer_id = %s', table('subscribers'), table('blacklists'), table('mail_lists'), db_quote(Subscriber::STATUS_BLACKLISTED), db_quote(Subscriber::STATUS_SUBSCRIBED), $customer->id);
            \DB::statement($sql);
        }
    }

    /**
     * Filter items.
     *
     * @return collect
     */
    public static function filter($request)
    {
        $user = $request->user();
        $query = self::select('blacklists.*');

        // Keyword
        if (!empty(trim($request->keyword))) {
            foreach (explode(' ', trim($request->keyword)) as $keyword) {
                $query = $query->where(function ($q) use ($keyword) {
                    $q->orwhere('blacklists.email', 'like', '%'.$keyword.'%');
                });
            }
        }

        // Other filter
        if (!empty($request->customer_id)) {
            $query = $query->where('blacklists.customer_id', '=', $request->customer_id);
        }

        if (!empty($request->admin_id)) {
            $query = $query->whereNull('customer_id');
        }

        return $query;
    }

    /**
     * Search items.
     *
     * @return collect
     */
    public static function search($request)
    {
        $query = self::filter($request);

        if (!empty($request->sort_order)) {
            $query = $query->orderBy($request->sort_order, $request->sort_direction);
        }

        return $query;
    }

    /**
     * Items per page.
     *
     * @var array
     */
    public static $itemsPerPage = 25;

    /**
     * Import from file.
     *
     * @return collect
     */
    public static function import($file, $customer = null, $progressCallback = null)
    {
        $failed = 0;
        $processed = 0;

        list($headers, $total, $results) = read_csv($file);

        if (!is_null($progressCallback)) {
            $progressCallback($processed, $total, $failed, $message = 'Loading file content...');
        }

        $customerId = (is_null($customer)) ? null : $customer->id;

        each_batch($results, $batchSize = config('custom.import_batch_size'), $skipHeader = false, function ($batch) use ($customerId, &$processed, &$failed, $total, $progressCallback) {
            // Insert subscriber fields from the batch to the temporary table
            // extract only fields whose name matches TAG NAME of MailList

            $data = collect($batch)->map(function ($r) use ($customerId) {
                $record = [
                    'email' => $r[0],
                    'customer_id' => $customerId,
                ];

                // replace the non-break space (not a normal space) as well as all other spaces
                $record['email'] = strtolower(preg_replace('/[ \s*]*/', '', trim($record['email'])));

                // In certain cases, a UTF-8 BOM is added to email
                // For example: "[email protected]" (open with Sublime to see the char)
                // So we need to remove it, at least for email field
                $record['email'] = StringHelper::removeUTF8BOM($record['email']);

                return $record;
            })->toArray();


            // make the import data table unique by email
            $data = array_unique_by($data, function ($r) {
                return $r['email'];
            });

            // validate and filter out invalid records
            $data = array_where($data, function ($record) use (&$failed) {
                $valid = Tool::isValidEmail($record['email']);
                if (!$valid) {
                    $failed += 1;
                }

                return $valid;
            });

            $tmpTableName = static::createTmpTableForImporting();

            DB::table($tmpTableName)->insert($data);

            $insertSql = strtr(
                '

                INSERT INTO %blacklists (email, customer_id, created_at, updated_at)
                SELECT tmp.email, %customer_id, NOW(), NOW()
                FROM %tmp tmp
                LEFT JOIN %blacklists main ON (tmp.email = main.email)
                WHERE main.email IS NULL',
                [
                    '%blacklists' => table('blacklists'),
                    '%customer_id' => $customerId ?? 'NULL',
                    '%tmp' => table($tmpTableName),
                ]
            );

            // Actually INSERT
            DB::statement($insertSql);

            $processed += sizeof($batch);

            if (!is_null($progressCallback)) {
                $progressCallback($processed, $total, $failed, trans('messages.blacklist.import_process_running', ['processed' => $processed]));
            }
        });

        self::doBlacklist($customer);

        if (!is_null($progressCallback)) {
            $progressCallback($processed = $total, $total, $failed, trans('messages.blacklist.import_process_complete', ['processed' => $total]));
        }
    }

    public static function upload(\Illuminate\Http\UploadedFile $httpFile)
    {
        $filename = "blacklst-import-".uniqid().".txt";
        $path = storage_path(self::IMPORT_TEMP_DIR);

        // store it to storage/
        $httpFile->move($path, $filename);

        // Example of outcome: /home/acelle/storage/app/tmp/import-000000.csv
        $filepath = join_paths($path, $filename);

        return $filepath;
    }

    /**
     * Add email to admin blacklist.
     */
    public static function addEmaill($email)
    {
        $email = trim(strtolower($email));

        if (Tool::isValidEmail($email)) {
            $exist = self::global()->where('email', '=', $email)->count();

            if (!$exist) {
                $blacklist = new self();
                $blacklist->email = $email;
                $blacklist->save();
            }
        }
    }

    public static function createTmpTableForImporting()
    {
        $tmpTableName = '__tmp_blacklist';
        $tmpTable = table($tmpTableName);

        // @todo: hard-coded charset and COLLATE
        $sql = "CREATE TABLE {$tmpTable}(`email` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, `customer_id` INTEGER) ENGINE=InnoDB;";
        DB::statement("DROP TABLE IF EXISTS {$tmpTable};"); // Seperate queries
        DB::statement($sql);

        return $tmpTableName;
    }
}