<?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, [
'~' => '\~',
'\\' => '\',
'{host}' => $site['host'],
'{domain}' => $site['domain']
]);
$sites["~$str(.*?)(\s|$)~ui"] = $this->replace . '$2';
}
}
return $sites;
}
}