Класс для замены/поиска чёрных сайтов

1.93K
.
The Fast, Secure and Professional - Yii2
Koenig, Может сегодня ближе к ночи.
.
Rakovskiy
The Fast, Secure and Professional - Yii2
Ну кароче почти дописал, осталось сделать изменение маски, ошибки из констант перенести в массив и исправить несколько багов (я думаю их несколько).

Вот пример http://chegos.hol.es/bls/example Можно заточить очень просто под любой двиг.
Прикрепленные файлы:
.
The Fast, Secure and Professional - Yii2
Код в example реально жёсткий, но можно увидеть как работает класс
.
The Fast, Secure and Professional - Yii2
Хотелось бы сейчас услышать, что написано не правильно, дабы к релизу всё исправить.
.
(\/)____o_O____(\/)
Rakovskiy, mb_strlen($host) === 0 имхо $host == '' , три равно тип еще проверяет, то есть чуть медленее
.
johncms.com
johncms - домен. ни какой не хост.
.com - доменная зона. не домен
.
The Fast, Secure and Professional - Yii2
# ramzes (26.02.2015 / 23:28)
johncms.com
johncms - домен. ни какой не хост.
.com - доменная зона. не домен
Угу, исправлю
.
The Fast, Secure and Professional - Yii2
# Koenig (26.02.2015 / 22:37)
Rakovskiy, mb_strlen($host) === 0 имхо $host == '' , три равно тип еще проверяет, то есть чуть медленее
Ну не знаю чё так, но $host == '' мне как-то не по душе
.
The Fast, Secure and Professional - Yii2
<?php
/**
 * RBlackListSitesConfig class file.
 *
 * @author Andrey Rakovskiy <rakovskiy28@mail.ru>
 * @link http://vk.com/rakovskiy28
 * @copyright 2015 Developed by Rakovskiy
 * @version 2.0
 */

class RBlackListSitesConfig {
    /**
     * Текст ошибки, если такая маска уже существует в ЧС
     */
    const ERROR_MASK_EXISTS = 'Такая маска уже существует';

    /**
     * Текст ошибки, если нету {host} или {domain}
     */
    const ERROR_MASK_NOT_HOST_OR_DOMAIN = 'Не указан {host} или {domain}';

    /**
     * Текст ошибки, если не указан хост или домен
     */
    const ERROR_SITE_NOT_HOST_OR_DOMAIN = 'Домен или хост не может быть пустым';

    /**
     * Текст ошибки, если такой сайт уже существует в ЧС
     */
    const ERROR_SITE_EXISTS = 'Такой сайт уже внесён в ЧС';

    /**
     * Текст ошибки, если конфиг не сохранился
     */
    const ERROR_SAVE = 'Конфигурация не сохранена, проверьте права доступа на директорию для сохранения конфига';

    /**
     * Текст ошибки, если сайт не найден по запросу
     */
    const ERROR_SITE_NOT_FOUND = 'Сайт не найден';

    /**
     * Текст ошибки, если маска не найдена
     */
    const ERROR_MASK_NOT_EXISTS = 'Маска не найдена';

    /**
     * Текст ошибки, если сайт не найден
     */
    const ERROR_SITE_NOT_EXISTS = 'Сайт не найден';

    /**
     * Конфигурация запрещённых сайтов
     * @var array
     */
    private $config = [];

    /**
     * Файл с конфигурацией
     * @var string
     */
    private $config_file;

    /**
     * Ошибки валидации
     * @var array
     */
    private $errors = [];

    /**
     * @param $config_file string Файл с конфигурацией
     * @throws Exception
     */
    public function __construct($config_file){
        $this->config_file = $config_file;

        if (file_exists($this->config_file)){
            $this->config = json_decode(file_get_contents($this->config_file), true);
        }

        if (isset($this->config['sites']) === false || is_array($this->config['sites']) === false){
            $this->config['sites'] = [];
        }

        if (isset($this->config['mask']) === false || is_array($this->config['mask']) === false){
            $this->config['mask'] = [];
        }

        if (isset($this->config['replace']) === false || is_string($this->config['replace']) === false){
            $this->config['replace'] = '***SPAM***';
        }
    }

    /**
     * Проверка наличия сайта, если есть возвращает ключ, если нет false
     * @param $host string
     * @param $domain string
     * @return bool|int|string
     */
    public function siteExists($host, $domain){
        foreach ($this->config['sites'] as $key => $site){
            if (isset($site['host'], $site['domain']) === false){
                continue;
            }
            if ($site['host'] === $host && $site['domain'] === $domain){
                return $key;
            }
        }

        return false;
    }

    /**
     * Валидация сайта
     * @param $host string
     * @param $domain string
     * @return bool
     * @throws Exception
     */
    private function validateSite($host, $domain){
        if (is_string($host) === false || is_string($domain) === false){
            throw new Exception('Неверный тип данных $host или $domain');
        }

        $error_key = $host . '.' . $domain;

        if (isset($this->errors[$error_key])){
            return false;
        }

        if (mb_strlen($host) === 0 || mb_strlen($domain) === 0){
            $this->errors[$error_key] = static::ERROR_SITE_NOT_HOST_OR_DOMAIN;
            return false;
        }

        if ($this->siteExists($host, $domain) !== false){
            $this->errors[$error_key] = static::ERROR_SITE_EXISTS;
            return false;
        }

        return true;
    }

    /**
     * Валидация маски
     * @param $mask string
     * @return bool
     * @throws Exception
     */
    private function validateMask($mask){
        if (is_string($mask) === false){
            throw new Exception('Неверный тип данных $mask');
        }

        if (isset($this->errors[$mask])){
            return false;
        }

        if (preg_match('/\{host\}/', $mask) === 0 || preg_match('/\{domain\}/', $mask) === 0){
            $this->errors[$mask] = static::ERROR_MASK_NOT_HOST_OR_DOMAIN;
            return false;
        }

        if (in_array($mask, $this->config['mask']) === true){
            $this->errors[$mask] = static::ERROR_MASK_EXISTS;
            return false;
        }

        return true;
    }

    /**
     * Добавляем новый сайт в ЧС
     * @param $host string
     * @param $domain string
     * @return bool
     * @throws Exception
     */
    public function addSite($host, $domain){
        if ($this->validateSite($host, $domain)){
            $this->config['sites'][] = [
                'host' => trim($host),
                'domain' => trim($domain)
            ];
            return true;
        }

        return false;
    }

    /**
     * Добавляем новую маску
     * @param $mask string
     * @return bool
     * @throws Exception
     */
    public function addMask($mask){
        if ($this->validateMask($mask)){
            $this->config['mask'][] = trim($mask);
            return true;
        }

        return false;
    }

    /**
     * Изменяем текст на который будем заменять сайты из ЧС
     * @param $text string
     * @return bool
     * @throws Exception
     */
    public function updateReplaceText($text){
        if (is_string($text) === false){
            throw new Exception('Неверный тип данных $text');
        }

        $this->config['replace'] = trim($text);
        return true;
    }

    /**
     * Изменяем сайт
     * @param $site array
     * @param $host string
     * @param $domain string
     * @return bool
     * @throws Exception
     */
    public function updateSite($site, $host, $domain){
        if (isset($site['host'], $site['domain']) === false || ($key = $this->siteExists($site['host'], $site['domain'])) === false){
            $this->errors[] = static::ERROR_SITE_NOT_FOUND;
            return false;
        }elseif ($this->validateSite($host, $domain) === true){
            $this->config['sites'][$key] = [
                'host' => trim($host),
                'domain' => trim($domain)
            ];
            return true;
        }
    }

    /**
     * Сохраняем конфигурацию
     * @return bool
     */
    public function save(){
        $config = json_encode($this->config);

        if (file_put_contents($this->config_file, $config) !== null){
            return true;
        }else{
            $this->errors[] = static::ERROR_SAVE;
            return false;
        }
    }

    /**
     * Удаление маски
     * @param $mask string
     * @return bool
     * @throws Exception
     */
    public function removeMask($mask){
        if (is_string($mask) === false){
            throw new Exception('Неверный тип данных $mask');
        }

        $key = array_search($mask, $this->config['mask']);
        if ($key !== false){
            unset($this->config['mask'][$key]);
            return $this->save();
        }

        $this->errors[] = static::ERROR_MASK_NOT_EXISTS;
        return false;
    }

    /**
     * Удаление сайта
     * @param $host string
     * @param $domain string
     * @return bool
     * @throws Exception
     */
    public function removeSite($host, $domain){
        if (is_string($host) === false || is_string($domain) === false){
            throw new Exception('Неверный тип данных $host или $domain');
        }

        if (($key = $this->siteExists($host, $domain)) !== false){
            unset($this->config['sites'][$key]);
            return $this->save();
        }

        $this->errors[] = static::ERROR_SITE_NOT_EXISTS;
        return false;
    }

    /**
     * Очистка всех сайтов
     * @return bool
     */
    public function removeAllSites(){
        $this->config['sites'] = [];
        return $this->save();
    }

    /**
     * Очистка всех масок
     * @return bool
     */
    public function removeAllMask(){
        $this->config['mask'] = [];
        return $this->save();
    }

    /**
     * Выводим все ошибки
     * @return array
     */
    public function getErrors(){
        return $this->errors;
    }

    /**
     * Проверяем, есть ли ошибки
     * @return bool
     */
    public function hasErrors(){
        return count($this->errors) > 0;
    }

    /**
     * Получаем конфигурацию
     * @return array
     */
    public function getConfig(){
        return $this->config;
    }

    /**
     * Получаем один сайт
     * @param $host string
     * @param $domain string
     * @return bool|int|string
     */
    public function getSite($host, $domain){
        if (($key = $this->siteExists($host, $domain)) !== false){
            return $this->config['sites'][$key];
        }

        return false;
    }

    /**
     * Получаем все сайты из ЧС
     * @return array
     */
    public function getSites(){
        return $this->config['sites'];
    }

    /**
     * Получаем все маски из ЧС
     * @return array
     */
    public function getMasks(){
        return $this->config['mask'];
    }

    /**
     * Получаем текст который заменяет сайт из ЧС
     * @return string
     */
    public function getReplaceText(){
        return $this->config['replace'];
    }
}


<?php
/**
 * RBlackListSites class file.
 *
 * @author Andrey Rakovskiy <rakovskiy28@mail.ru>
 * @link http://vk.com/rakovskiy28
 * @copyright 2015 Developed by Rakovskiy
 * @version 2.0
 */

class RBlackListSites {
    /**
     * Список доменов
     * @var array
     */
    private $sites = [];

    /**
     * Список масок
     * @var array
     */
    private $mask = [];

    /**
     * На что меняем запрещённый сайт
     * @var string
     */
    private $replace;

    /**
     * @param $config array Конфигурация
     */
    public function __construct($config){
        $this->sites = isset($config['sites']) ? $config['sites'] : [];
        $this->mask = isset($config['mask']) ? $config['mask'] : [];
        $this->replace = isset($config['replace']) ? $config['replace'] : '***SPAM***';
    }

    /**
     * Заменяем все запрещённые сайты в тексте
     * @param $text string
     * @return mixed
     */
    public function run($text){
        $sites = $this->collectOptions();
        return preg_replace(array_keys($sites), array_values($sites), $text);
    }

    /**
     * Проверяем, есть ли в тексте запрещённые сайты
     * @param $text string
     * @return bool
     */
    public function has($text){
        return $this->run($text) != $text;
    }

    /**
     * Собираем в массив возможные варианты написания сайтов в тексте
     * @return array
     */
    private function collectOptions(){
        $sites = [];

        foreach ($this->sites as $site){
            foreach ($this->mask as $mask){
                if (isset($site['host'], $site['host']) === false){
                    continue;
                }
                $str = strtr($mask, [
                    '~' => '\~',
                    '\\' => '&#92;',
                    '{host}' => $site['host'],
                    '{domain}' => $site['domain']
                ]);

                $sites["~$str(.*?)(\s|$)~ui"] = $this->replace . '$2';
            }
        }

        return $sites;
    }
}
.
(\/)____o_O____(\/)
Rakovskiy, ну и класс конфига ты перегрузил, тебе нужен класс приложения, которое будет работать с конфигом, то есть add, isset_key ... , ну а класс приложения уже будет проверять и прочее
Всего: 90