mirror of
https://github.com/e107inc/e107.git
synced 2025-07-26 01:11:28 +02:00
News SEF URL for tags. Automatically switch URL path to lowercase when lowercase url template is used.
This commit is contained in:
@@ -490,7 +490,8 @@ class news_shortcodes extends e_shortcode
|
|||||||
{
|
{
|
||||||
if(trim($val))
|
if(trim($val))
|
||||||
{
|
{
|
||||||
$words[] = "<a href='".e_BASE."news.php?tag=".$val."'><span class='label label-default'>".$val."</span></a>";
|
$url = e107::getUrl()->create('news/list/tag',array('tag'=>$val)); // e_BASE."news.php?tag=".$val
|
||||||
|
$words[] = "<a href='".$url."'><span class='label label-default'>".$val."</span></a>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,14 +35,16 @@ class core_news_sef_full_url extends eUrlConfig
|
|||||||
'Category/<name:{sefsecure}>' => array('list/category', 'allowVars' => array('page'), 'mapVars' => array('category_sef' => 'name'), 'legacyQuery' => 'list.{name}.{page}', 'parseCallback' => 'categoryIdByTitle'),
|
'Category/<name:{sefsecure}>' => array('list/category', 'allowVars' => array('page'), 'mapVars' => array('category_sef' => 'name'), 'legacyQuery' => 'list.{name}.{page}', 'parseCallback' => 'categoryIdByTitle'),
|
||||||
'All' => array('list/all', 'allowVars' => array('page'), 'legacyQuery' => 'all.0.{page}'),
|
'All' => array('list/all', 'allowVars' => array('page'), 'legacyQuery' => 'all.0.{page}'),
|
||||||
|
|
||||||
'Short/<name:{sefsecure}>' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_sef' => 'name'), 'legacyQuery' => 'cat.{name}.{page}', 'parseCallback' => 'categoryIdByTitle'),
|
'Short/<name:{sefsecure}>' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_sef' => 'name'), 'legacyQuery' => 'cat.{name}.{page}', 'parseCallback' => 'categoryIdByTitle'),
|
||||||
'Short/<id:{number}>' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_id' => 'id'), 'legacyQuery' => 'cat.{id}.{page}'),
|
'Short/<id:{number}>' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_id' => 'id'), 'legacyQuery' => 'cat.{id}.{page}'),
|
||||||
'Day/<id:{number}>' => array('list/day', 'allowVars' => array('page'), 'legacyQuery' => 'day.{id}.{page}'),
|
'Day/<id:{number}>' => array('list/day', 'allowVars' => array('page'), 'legacyQuery' => 'day.{id}.{page}'),
|
||||||
'Month/<id:{number}>' => array('list/month', 'allowVars' => array('page'), 'legacyQuery' => 'month.{id}.{page}'),
|
'Month/<id:{number}>' => array('list/month', 'allowVars' => array('page'), 'legacyQuery' => 'month.{id}.{page}'),
|
||||||
|
'Tag/<tag:{secure}>' => array('list/tag', 'allowVars' => array('page'), 'legacyQuery' => 'tag={tag}'),
|
||||||
|
|
||||||
'<category:{sefsecure}>/<name:{sefsecure}>' => array('view/item', 'mapVars' => array('category_sef' => 'category', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'),
|
'<category:{sefsecure}>/<name:{sefsecure}>' => array('view/item', 'mapVars' => array('category_sef' => 'category', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'),
|
||||||
'<name:{sefsecure}>' => array('view/item', 'mapVars' => array('news_id' => 'id', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'),
|
'<name:{sefsecure}>' => array('view/item', 'mapVars' => array('news_id' => 'id', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'),
|
||||||
'<id:{number}>' => array('view/item', 'mapVars' => array('news_id' => 'id'), 'legacyQuery' => 'extend.{id}'),
|
'<id:{number}>' => array('view/item', 'mapVars' => array('news_id' => 'id'), 'legacyQuery' => 'extend.{id}'),
|
||||||
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -97,6 +97,11 @@ class core_news_sef_noid_url extends eUrlConfig
|
|||||||
if($page) $parm = array('page' => $page); // news/All?page=xxx
|
if($page) $parm = array('page' => $page); // news/All?page=xxx
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'tag': // news/tag/xxxx
|
||||||
|
$r[0] = 'tag';
|
||||||
|
$r[1] = $params['tag'];
|
||||||
|
break;
|
||||||
|
|
||||||
case 'category':
|
case 'category':
|
||||||
case 'short':
|
case 'short':
|
||||||
if(!vartrue($params['id']))
|
if(!vartrue($params['id']))
|
||||||
@@ -154,8 +159,9 @@ class core_news_sef_noid_url extends eUrlConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
## no controller/action pair - news item view - map to extend.xxx
|
## no controller/action pair - news item view - map to extend.xxx
|
||||||
if(strpos($pathInfo, '/') === false && $pathInfo != 'All')
|
if(strpos($pathInfo, '/') === false && strtolower($pathInfo) != 'all')
|
||||||
{
|
{
|
||||||
|
|
||||||
$route = 'view/item';
|
$route = 'view/item';
|
||||||
$id = is_numeric($pathInfo) ? intval($pathInfo) : $this->itemIdByTitle($pathInfo);
|
$id = is_numeric($pathInfo) ? intval($pathInfo) : $this->itemIdByTitle($pathInfo);
|
||||||
if(!$id)
|
if(!$id)
|
||||||
@@ -228,6 +234,11 @@ class core_news_sef_noid_url extends eUrlConfig
|
|||||||
return 'list/all';
|
return 'list/all';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'tag':
|
||||||
|
$this->legacyQueryString = 'tag='.$parts[1];
|
||||||
|
return 'list/tag';
|
||||||
|
break;
|
||||||
|
|
||||||
# force not found
|
# force not found
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@@ -105,7 +105,10 @@ class core_news_sef_url extends eUrlConfig
|
|||||||
// fallback if news sef is missing
|
// fallback if news sef is missing
|
||||||
'View/<id:{number}>/<name:{sefsecure}>' => array('view/item', 'mapVars' => array('news_id' => 'id', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{id}'),
|
'View/<id:{number}>/<name:{sefsecure}>' => array('view/item', 'mapVars' => array('news_id' => 'id', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{id}'),
|
||||||
|
|
||||||
'View/<id:{number}>' => array('view/item', 'mapVars' => array('news_id' => 'id'), 'legacyQuery' => 'extend.{id}'),
|
'View/<id:{number}>' => array('view/item', 'mapVars' => array('news_id' => 'id'), 'legacyQuery' => 'extend.{id}'),
|
||||||
|
|
||||||
|
'Tag/<tag:{secure}>' => array('list/tag', 'allowVars' => array('page'), 'legacyQuery' => 'tag={tag}'),
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -113,7 +116,7 @@ class core_news_sef_url extends eUrlConfig
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Query mapping in format route?params:
|
* Query mapping in format route?params:
|
||||||
* - item/vew?id=xxx -> ?extend.id
|
* - item/view?id=xxx -> ?extend.id
|
||||||
* - list/items[?page=xxx] -> default.0.page
|
* - list/items[?page=xxx] -> default.0.page
|
||||||
* - list/category?id=xxx[&page=xxx] -> list.id.page
|
* - list/category?id=xxx[&page=xxx] -> list.id.page
|
||||||
* - list/category?id=0[&page=xxx] -> default.0.page
|
* - list/category?id=0[&page=xxx] -> default.0.page
|
||||||
|
@@ -95,6 +95,7 @@ class core_news_url extends eUrlConfig
|
|||||||
$route[1] = 'items';
|
$route[1] = 'items';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return print_a($route,true);
|
||||||
## news are passing array as it is retrieved from the DB, map vars to proper values
|
## news are passing array as it is retrieved from the DB, map vars to proper values
|
||||||
if(isset($params['news_id']) && !empty($params['news_id'])) $params['id'] = $params['news_id'];
|
if(isset($params['news_id']) && !empty($params['news_id'])) $params['id'] = $params['news_id'];
|
||||||
//if(isset($params['news_sef']) && !empty($params['news_sef'])) $params['id'] = $params['news_sef'];
|
//if(isset($params['news_sef']) && !empty($params['news_sef'])) $params['id'] = $params['news_sef'];
|
||||||
@@ -142,6 +143,10 @@ class core_news_url extends eUrlConfig
|
|||||||
$url .= 'all.'.$params['id'].'.'.$page;
|
$url .= 'all.'.$params['id'].'.'.$page;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'tag':
|
||||||
|
$url .= 'tag='.$params['id'].'&page='.$page;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'short':
|
case 'short':
|
||||||
$url .= 'cat.'.$params['id'].'.'.$page;
|
$url .= 'cat.'.$params['id'].'.'.$page;
|
||||||
break;
|
break;
|
||||||
@@ -158,7 +163,10 @@ class core_news_url extends eUrlConfig
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else $url = 'news.php';
|
else
|
||||||
|
{
|
||||||
|
$url = 'news.php';
|
||||||
|
}
|
||||||
|
|
||||||
return $url;
|
return $url;
|
||||||
}
|
}
|
||||||
|
@@ -72,6 +72,11 @@ class core_page_sef_noid_url extends eUrlConfig
|
|||||||
public function itemIdByTitle(eRequest $request)
|
public function itemIdByTitle(eRequest $request)
|
||||||
{
|
{
|
||||||
$name = $request->getRequestParam('name');
|
$name = $request->getRequestParam('name');
|
||||||
|
|
||||||
|
e107::getMessage()->addDebug('name = '.$name);
|
||||||
|
e107::getMessage()->addDebug(print_r($request,true));
|
||||||
|
e107::getAdminLog()->toFile('page_sef_noid_url');
|
||||||
|
|
||||||
if(($id = $request->getRequestParam('id')))
|
if(($id = $request->getRequestParam('id')))
|
||||||
{
|
{
|
||||||
$request->setRequestParam('name', $id);
|
$request->setRequestParam('name', $id);
|
||||||
@@ -79,6 +84,9 @@ class core_page_sef_noid_url extends eUrlConfig
|
|||||||
}
|
}
|
||||||
elseif(!$name || is_numeric($name)) return;
|
elseif(!$name || is_numeric($name)) return;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$sql = e107::getDb('url');
|
$sql = e107::getDb('url');
|
||||||
$name = e107::getParser()->toDB($name);
|
$name = e107::getParser()->toDB($name);
|
||||||
if($sql->db_Select('page', 'page_id', "menu_name='' AND page_sef='{$name}'"))
|
if($sql->db_Select('page', 'page_id', "menu_name='' AND page_sef='{$name}'"))
|
||||||
|
@@ -1810,6 +1810,7 @@ class eRouter
|
|||||||
|
|
||||||
$anc = '';
|
$anc = '';
|
||||||
|
|
||||||
|
|
||||||
if(is_string($params)) parse_str($params, $params);
|
if(is_string($params)) parse_str($params, $params);
|
||||||
if(isset($params['#']))
|
if(isset($params['#']))
|
||||||
{
|
{
|
||||||
@@ -1897,8 +1898,6 @@ class eRouter
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# aliases
|
# aliases
|
||||||
$module = $route[0];
|
$module = $route[0];
|
||||||
$config = $this->getConfig($module);
|
$config = $this->getConfig($module);
|
||||||
@@ -1974,7 +1973,10 @@ class eRouter
|
|||||||
{
|
{
|
||||||
foreach ($rules as $k => $rule)
|
foreach ($rules as $k => $rule)
|
||||||
{
|
{
|
||||||
if (($url = $rule->createUrl($this, array($route[1], $route[2]), $params, $options)) !== false) return $base.rtrim(($this->isMainModule($module) ? '' : $alias.'/').$url, '/').$anc;
|
if (($url = $rule->createUrl($this, array($route[1], $route[2]), $params, $options)) !== false)
|
||||||
|
{
|
||||||
|
return $base.rtrim(($this->isMainModule($module) ? '' : $alias.'/').$url, '/').$anc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2037,6 +2039,8 @@ class eRouter
|
|||||||
}
|
}
|
||||||
$route = implode('/', $route);
|
$route = implode('/', $route);
|
||||||
if(!$route || $route == $alias) $urlSuffix = '';
|
if(!$route || $route == $alias) $urlSuffix = '';
|
||||||
|
|
||||||
|
|
||||||
return $format === self::FORMAT_GET ? $base.'?'.$this->routeVar.'='.$route.$anc : $base.$route.$urlSuffix.$anc;
|
return $format === self::FORMAT_GET ? $base.'?'.$this->routeVar.'='.$route.$anc : $base.$route.$urlSuffix.$anc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2392,6 +2396,8 @@ class eUrlRule
|
|||||||
|
|
||||||
if(is_array($route)) $route = implode('/', $route);
|
if(is_array($route)) $route = implode('/', $route);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$tr = array();
|
$tr = array();
|
||||||
if ($route !== $this->route)
|
if ($route !== $this->route)
|
||||||
{
|
{
|
||||||
@@ -2411,7 +2417,7 @@ class eUrlRule
|
|||||||
unset($params[$srcKey]);
|
unset($params[$srcKey]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// false means - no vars are allowed, preserve only route vars
|
// false means - no vars are allowed, preserve only route vars
|
||||||
if($this->allowVars === false) $this->allowVars = array_keys($this->params);
|
if($this->allowVars === false) $this->allowVars = array_keys($this->params);
|
||||||
// empty array (default) - everything is allowed
|
// empty array (default) - everything is allowed
|
||||||
@@ -2460,7 +2466,7 @@ class eUrlRule
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->params as $key => $value)
|
foreach ($this->params as $key => $value)
|
||||||
{
|
{
|
||||||
// FIX - non-latin URLs proper encoded
|
// FIX - non-latin URLs proper encoded
|
||||||
@@ -2470,9 +2476,19 @@ class eUrlRule
|
|||||||
|
|
||||||
$suffix = $this->urlSuffix === null ? $manager->urlSuffix : $this->urlSuffix;
|
$suffix = $this->urlSuffix === null ? $manager->urlSuffix : $this->urlSuffix;
|
||||||
|
|
||||||
|
$urlFormat = e107::getConfig()->get('url_sef_translate');
|
||||||
|
|
||||||
|
if($urlFormat == 'dashl' || $urlFormat == 'underscorel' || $urlFormat == 'plusl') // convert template to lowercase when using lowercase SEF URL format.
|
||||||
|
{
|
||||||
|
$this->template = strtolower($this->template);
|
||||||
|
}
|
||||||
|
|
||||||
$url = strtr($this->template, $tr);
|
$url = strtr($this->template, $tr);
|
||||||
|
|
||||||
if (empty($params)) return $url !== '' ? $url.$suffix : $url;
|
if(empty($params))
|
||||||
|
{
|
||||||
|
return $url !== '' ? $url.$suffix : $url;
|
||||||
|
}
|
||||||
|
|
||||||
// apppend not supported, maybe in the future...?
|
// apppend not supported, maybe in the future...?
|
||||||
if ($this->append) $url .= '/'.$manager->createPathInfo($params, '/', '/').$suffix;
|
if ($this->append) $url .= '/'.$manager->createPathInfo($params, '/', '/').$suffix;
|
||||||
@@ -2483,6 +2499,7 @@ class eUrlRule
|
|||||||
$options['equal'] = '=';
|
$options['equal'] = '=';
|
||||||
$url .= '?'.$manager->createPathInfo($params, $options);
|
$url .= '?'.$manager->createPathInfo($params, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return rtrim($url, '/');
|
return rtrim($url, '/');
|
||||||
}
|
}
|
||||||
@@ -3540,6 +3557,7 @@ class eRequest
|
|||||||
public function populateRequestParams()
|
public function populateRequestParams()
|
||||||
{
|
{
|
||||||
$rp = $this->getRequestParams();
|
$rp = $this->getRequestParams();
|
||||||
|
|
||||||
foreach ($rp as $key => $value)
|
foreach ($rp as $key => $value)
|
||||||
{
|
{
|
||||||
$_GET[$key] = $value;
|
$_GET[$key] = $value;
|
||||||
|
@@ -42,9 +42,9 @@ class news_sitelink // include plugin-folder in the name.
|
|||||||
$nobody_regexp = "'(^|,)(".str_replace(",", "|", e_UC_NOBODY).")(,|$)'";
|
$nobody_regexp = "'(^|,)(".str_replace(",", "|", e_UC_NOBODY).")(,|$)'";
|
||||||
$query = "SELECT * FROM #news WHERE news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (news_class REGEXP ".$nobody_regexp.") ORDER BY news_datestamp DESC LIMIT 10";
|
$query = "SELECT * FROM #news WHERE news_class REGEXP '".e_CLASS_REGEXP."' AND NOT (news_class REGEXP ".$nobody_regexp.") ORDER BY news_datestamp DESC LIMIT 10";
|
||||||
|
|
||||||
if($sql->db_Select_gen($query))
|
if($sql->gen($query))
|
||||||
{
|
{
|
||||||
while($row = $sql->db_Fetch())
|
while($row = $sql->fetch())
|
||||||
{
|
{
|
||||||
$sublinks[] = array(
|
$sublinks[] = array(
|
||||||
'link_name' => $row['news_title'],
|
'link_name' => $row['news_title'],
|
||||||
@@ -60,8 +60,8 @@ class news_sitelink // include plugin-folder in the name.
|
|||||||
}
|
}
|
||||||
|
|
||||||
$sublinks[] = array(
|
$sublinks[] = array(
|
||||||
'link_name' => "More...",
|
'link_name' => LAN_MORE,
|
||||||
'link_url' => 'news.php?all', // e107::getUrl()->create('news/list/all'), // XXX TODO FIXME Not behaving the same as legacy url.
|
'link_url' => e107::getUrl()->create('news/list/all'),
|
||||||
'link_description' => '',
|
'link_description' => '',
|
||||||
'link_button' => '',
|
'link_button' => '',
|
||||||
'link_category' => '',
|
'link_category' => '',
|
||||||
|
28
news.php
28
news.php
@@ -84,6 +84,10 @@ if ($action == 'all' || $action == 'cat')
|
|||||||
$sub_action = intval(varset($tmp[1],0));
|
$sub_action = intval(varset($tmp[1],0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Variables Used:
|
Variables Used:
|
||||||
$action - the basic display format/filter
|
$action - the basic display format/filter
|
||||||
@@ -129,9 +133,30 @@ $nobody_regexp = "'(^|,)(".str_replace(",", "|", e_UC_NOBODY).")(,|$)'";
|
|||||||
$newsRoute = 'list/all';
|
$newsRoute = 'list/all';
|
||||||
$newsUrlparms['id'] = $sub_action;
|
$newsUrlparms['id'] = $sub_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
else $newsRoute = 'list/items';
|
else $newsRoute = 'list/items';
|
||||||
$newsRoute = 'news/'.$newsRoute;
|
$newsRoute = 'news/'.$newsRoute;
|
||||||
|
|
||||||
|
|
||||||
|
if(vartrue($_GET['tag']) || substr($action,0,4) == 'tag=')
|
||||||
|
{
|
||||||
|
|
||||||
|
$newsRoute = 'news/list/tag';
|
||||||
|
if(!vartrue($_GET['tag']))
|
||||||
|
{
|
||||||
|
list($action,$word) = explode("=",$action,2);
|
||||||
|
$_GET['tag'] = $word;
|
||||||
|
unset($word,$tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
$newsfrom = intval(varset($_GET['page'],0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
echo "route= ".$newsRoute." ";
|
||||||
|
echo "<br />action= ".$action." ";
|
||||||
|
echo "<br />_GET= ".print_a($_GET,true);
|
||||||
|
*/
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
// DISPLAY NEWS IN 'CATEGORY' LIST FORMAT HERE
|
// DISPLAY NEWS IN 'CATEGORY' LIST FORMAT HERE
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
@@ -207,6 +232,7 @@ if ($action == 'cat' || $action == 'all' || vartrue($_GET['tag']))
|
|||||||
ORDER BY n.news_datestamp DESC
|
ORDER BY n.news_datestamp DESC
|
||||||
LIMIT ".intval($newsfrom).",".NEWSLIST_LIMIT;
|
LIMIT ".intval($newsfrom).",".NEWSLIST_LIMIT;
|
||||||
$category_name = 'Tag: "'.$tagsearch.'"';
|
$category_name = 'Tag: "'.$tagsearch.'"';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$newsList = array();
|
$newsList = array();
|
||||||
@@ -292,7 +318,7 @@ if ($action == 'cat' || $action == 'all' || vartrue($_GET['tag']))
|
|||||||
$NEWSLISTTITLE = str_replace("{NEWSCATEGORY}",$tp->toHTML($category_name,FALSE,'TITLE'),$NEWSLISTTITLE);
|
$NEWSLISTTITLE = str_replace("{NEWSCATEGORY}",$tp->toHTML($category_name,FALSE,'TITLE'),$NEWSLISTTITLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
$text .= "<div class='center news-list-footer'><a class='btn btn-default' href='".e_REQUEST_SELF."'>".LAN_NEWS_84."</a></div>";
|
$text .= "<div class='center news-list-footer'><a class='btn btn-default' href='".e107::getUrl()->create('news/all')."'>".LAN_NEWS_84."</a></div>";
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
$ns->tablerender($NEWSLISTTITLE, $text, 'news');
|
$ns->tablerender($NEWSLISTTITLE, $text, 'news');
|
||||||
|
Reference in New Issue
Block a user