2017-10-03
2
.gitignore
vendored
|
@ -2,4 +2,4 @@
|
|||
/app/config/main.php
|
||||
/app/cache/**/*.php
|
||||
/app/cache/**/*.lock
|
||||
/public/avatar/*
|
||||
/public/img/avatars/*
|
||||
|
|
|
@ -81,7 +81,7 @@ class Routing
|
|||
$r->add('GET', '/forum/{id:[1-9]\d*}/new/topic', 'Post:newTopic', 'NewTopic');
|
||||
$r->add('GET', '/forum/{id:[1-9]\d*}[/{name}][/page/{page:[1-9]\d*}]', 'Forum:view', 'Forum');
|
||||
// темы
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}[/{name}][/page/{page:[1-9]\d*}]', 'Topic:view', 'Topic');
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}[/{name}][/page/{page:[1-9]\d*}]', 'Topic:viewTopic', 'Topic');
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}/goto/new', 'Topic:goToNew', 'TopicGoToNew');
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}/goto/unread', 'Topic:goToUnread', 'TopicGoToUnread');
|
||||
$r->add('GET', '/topic/{id:[1-9]\d*}/goto/last', 'Topic:goToLast', 'TopicGoToLast');
|
||||
|
|
78
app/Models/Pages/CrumbTrait.php
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
trait CrumbTrait
|
||||
{
|
||||
/**
|
||||
* Возвращает массив хлебных крошек
|
||||
* @param mixed $args
|
||||
* @return array
|
||||
*/
|
||||
protected function getCrumbs(...$args)
|
||||
{
|
||||
$crumbs = [];
|
||||
$active = true;
|
||||
|
||||
foreach ($args as $arg) {
|
||||
if (is_array($arg)) {
|
||||
$cur = array_shift($arg);
|
||||
// массив разделов
|
||||
if (is_array($cur)) {
|
||||
$id = $arg[0];
|
||||
while (true) {
|
||||
$this->titles[] = $cur[$id]['forum_name'];
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Forum', ['id' => $id, 'name' => $cur[$id]['forum_name']]),
|
||||
$cur[$id]['forum_name'],
|
||||
$active,
|
||||
];
|
||||
$active = null;
|
||||
if (! isset($cur[$id][0])) {
|
||||
break;
|
||||
}
|
||||
$id = $cur[$id][0];
|
||||
}
|
||||
// отдельная страница
|
||||
} else {
|
||||
// определение названия
|
||||
if (isset($arg[1])) {
|
||||
$vars = $arg[0];
|
||||
$name = $arg[1];
|
||||
} elseif (is_string($arg[0])) {
|
||||
$vars = [];
|
||||
$name = $arg[0];
|
||||
} elseif (isset($arg[0]['name'])) {
|
||||
$vars = $arg[0];
|
||||
$name = $arg[0]['name'];
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
$this->titles[] = $name;
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link($cur, $vars),
|
||||
$name,
|
||||
$active,
|
||||
];
|
||||
}
|
||||
// предположительно идет только название, без ссылки
|
||||
} else {
|
||||
$this->titles[] = (string) $arg;
|
||||
$crumbs[] = [
|
||||
null,
|
||||
(string) $arg,
|
||||
$active,
|
||||
];
|
||||
}
|
||||
$active = null;
|
||||
}
|
||||
// главная страница
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Index'),
|
||||
__('Index'),
|
||||
$active,
|
||||
];
|
||||
|
||||
return array_reverse($crumbs);
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ namespace ForkBB\Models\Pages;
|
|||
class Forum extends Page
|
||||
{
|
||||
use ForumsTrait;
|
||||
use CrumbTrait;
|
||||
|
||||
/**
|
||||
* Имя шаблона
|
||||
|
@ -189,33 +190,10 @@ class Forum extends Page
|
|||
|
||||
$this->onlinePos = 'forum-' . $args['id'];
|
||||
|
||||
$crumbs = [];
|
||||
$id = $args['id'];
|
||||
$activ = true;
|
||||
while (true) {
|
||||
$name = $fDesc[$id]['forum_name'];
|
||||
$this->titles[] = $name;
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Forum', ['id' => $id, 'name' => $name]),
|
||||
$name,
|
||||
$activ,
|
||||
];
|
||||
$activ = null;
|
||||
if (! isset($fDesc[$id][0])) {
|
||||
break;
|
||||
}
|
||||
$id = $fDesc[$id][0];
|
||||
}
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Index'),
|
||||
__('Index'),
|
||||
null,
|
||||
];
|
||||
|
||||
$this->data = [
|
||||
'forums' => $this->getForumsData($args['id']),
|
||||
'topics' => $topics,
|
||||
'crumbs' => array_reverse($crumbs),
|
||||
'crumbs' => $this->getCrumbs([$fDesc, $args['id']]),
|
||||
'forumName' => $fDesc[$args['id']]['forum_name'],
|
||||
'newTopic' => $newOn ? $this->c->Router->link('NewTopic', ['id' => $args['id']]) : null,
|
||||
'pages' => $this->c->Func->paginate($pages, $page, 'Forum', ['id' => $args['id'], 'name' => $fDesc[$args['id']]['forum_name']]),
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace ForkBB\Models\Pages;
|
|||
class Index extends Page
|
||||
{
|
||||
use ForumsTrait;
|
||||
use OnlineTrait;
|
||||
|
||||
/**
|
||||
* Имя шаблона
|
||||
|
@ -60,53 +61,11 @@ class Index extends Page
|
|||
$stats['newest_user'] = $stats['last_user']['username'];
|
||||
}
|
||||
$this->data['stats'] = $stats;
|
||||
|
||||
// вывод информации об онлайн посетителях
|
||||
if ($this->config['o_users_online'] == '1') {
|
||||
$this->data['online'] = [];
|
||||
$this->data['online']['max'] = $this->number($this->config['st_max_users']);
|
||||
$this->data['online']['max_time'] = $this->time($this->config['st_max_users_time']);
|
||||
|
||||
// данные онлайн посетителей
|
||||
list($users, $guests, $bots) = $this->c->Online->handle($this);
|
||||
$list = [];
|
||||
|
||||
if ($this->c->user->gViewUsers == '1') {
|
||||
foreach ($users as $id => $cur) {
|
||||
$list[] = [
|
||||
$this->c->Router->link('User', [
|
||||
'id' => $id,
|
||||
'name' => $cur['name'],
|
||||
]),
|
||||
$cur['name'],
|
||||
];
|
||||
}
|
||||
} else {
|
||||
foreach ($users as $cur) {
|
||||
$list[] = $cur['name'];
|
||||
}
|
||||
}
|
||||
$this->data['online']['number_of_users'] = $this->number(count($users));
|
||||
|
||||
$s = 0;
|
||||
foreach ($bots as $name => $cur) {
|
||||
$count = count($cur);
|
||||
$s += $count;
|
||||
if ($count > 1) {
|
||||
$list[] = '[Bot] ' . $name . ' (' . $count . ')';
|
||||
} else {
|
||||
$list[] = '[Bot] ' . $name;
|
||||
}
|
||||
}
|
||||
$s += count($guests);
|
||||
$this->data['online']['number_of_guests'] = $this->number($s);
|
||||
$this->data['online']['list'] = $list;
|
||||
} else {
|
||||
$this->onlineType = false;
|
||||
$this->c->Online->handle($this);
|
||||
$this->data['online'] = null;
|
||||
}
|
||||
$this->data['online'] = $this->getUsersOnlineInfo();
|
||||
$this->data['forums'] = $this->getForumsData();
|
||||
|
||||
$this->canonical = $this->c->Router->link('Index');
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
59
app/Models/Pages/OnlineTrait.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Models\Pages;
|
||||
|
||||
trait OnlineTrait
|
||||
{
|
||||
/**
|
||||
* Получение информации об онлайн посетителях
|
||||
* @return null|array
|
||||
*/
|
||||
protected function getUsersOnlineInfo()
|
||||
{
|
||||
if ($this->config['o_users_online'] == '1') {
|
||||
$data = [
|
||||
'max' => $this->number($this->config['st_max_users']),
|
||||
'max_time' => $this->time($this->config['st_max_users_time']),
|
||||
];
|
||||
|
||||
// данные онлайн посетителей
|
||||
list($users, $guests, $bots) = $this->c->Online->handle($this);
|
||||
$list = [];
|
||||
|
||||
if ($this->c->user->gViewUsers == '1') {
|
||||
foreach ($users as $id => $cur) {
|
||||
$list[] = [
|
||||
$this->c->Router->link('User', [
|
||||
'id' => $id,
|
||||
'name' => $cur['name'],
|
||||
]),
|
||||
$cur['name'],
|
||||
];
|
||||
}
|
||||
} else {
|
||||
foreach ($users as $cur) {
|
||||
$list[] = $cur['name'];
|
||||
}
|
||||
}
|
||||
$data['number_of_users'] = $this->number(count($users));
|
||||
|
||||
$s = 0;
|
||||
foreach ($bots as $name => $cur) {
|
||||
$count = count($cur);
|
||||
$s += $count;
|
||||
if ($count > 1) {
|
||||
$list[] = '[Bot] ' . $name . ' (' . $count . ')';
|
||||
} else {
|
||||
$list[] = '[Bot] ' . $name;
|
||||
}
|
||||
}
|
||||
$s += count($guests);
|
||||
$data['number_of_guests'] = $this->number($s);
|
||||
$data['list'] = $list;
|
||||
return $data;
|
||||
} else {
|
||||
$this->onlineType = false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,6 +34,9 @@ class Rules extends Page
|
|||
'rules' => $this->config['o_rules_message'],
|
||||
'formAction' => null,
|
||||
];
|
||||
|
||||
$this->canonical = $this->c->Router->link('Rules');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@ namespace ForkBB\Models\Pages;
|
|||
class Topic extends Page
|
||||
{
|
||||
use UsersTrait;
|
||||
|
||||
use OnlineTrait;
|
||||
use CrumbTrait;
|
||||
|
||||
/**
|
||||
* Имя шаблона
|
||||
* @var string
|
||||
|
@ -18,6 +20,22 @@ class Topic extends Page
|
|||
*/
|
||||
protected $onlinePos = 'topic';
|
||||
|
||||
/**
|
||||
* Тип обработки пользователей онлайн
|
||||
* Если false, то идет обновление данных
|
||||
* Если true, то идет возврат данных (смотрите $onlineFilter)
|
||||
* @var bool
|
||||
*/
|
||||
protected $onlineType = true;
|
||||
|
||||
/**
|
||||
* Тип возврата данных при onlineType === true
|
||||
* Если true, то из online должны вернутся только пользователи находящиеся на этой же странице
|
||||
* Если false, то все пользователи online
|
||||
* @var bool
|
||||
*/
|
||||
protected $onlineFilter = true;
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
* @param array $args
|
||||
|
@ -69,44 +87,37 @@ class Topic extends Page
|
|||
$vars = [
|
||||
':pid' => $args['id'],
|
||||
];
|
||||
$sql = 'SELECT topic_id FROM ::posts WHERE id=?i:pid';
|
||||
|
||||
$tid = $this->c->DB->query($sql, $vars)->fetchColumn();
|
||||
// сообшение не найдено в базе
|
||||
if (empty($tid)) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
if ($this->c->user->isGuest) {
|
||||
$sql = 'SELECT t.*, f.moderators, 0 AS is_subscribed
|
||||
FROM ::topics AS t
|
||||
INNER JOIN ::forums AS f ON f.id=t.forum_id
|
||||
INNER JOIN ::posts AS p ON t.id=p.topic_id
|
||||
WHERE p.id=?i:pid AND t.moved_to IS NULL';
|
||||
} else {
|
||||
$sql = 'SELECT t.*, f.moderators, s.user_id AS is_subscribed
|
||||
FROM ::topics AS t
|
||||
INNER JOIN ::forums AS f ON f.id=t.forum_id
|
||||
INNER JOIN ::posts AS p ON t.id=p.topic_id
|
||||
LEFT JOIN ::topic_subscriptions AS s ON (t.id=s.topic_id AND s.user_id=?i:uid)
|
||||
WHERE p.id=?i:pid AND t.moved_to IS NULL';
|
||||
}
|
||||
|
||||
$vars = [
|
||||
':pid' => $args['id'],
|
||||
':tid' => $tid,
|
||||
];
|
||||
$sql = 'SELECT COUNT(id) FROM ::posts WHERE topic_id=?i:tid AND id<?i:pid';
|
||||
|
||||
$num = 1 + $this->c->DB->query($sql, $vars)->fetchColumn();
|
||||
|
||||
return $this->view([
|
||||
'id' => $tid,
|
||||
'page' => ceil($num / $this->c->user->dispPosts),
|
||||
]);
|
||||
return $this->view($sql, $vars, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
* Просмотр темы по ее номеру
|
||||
* @param array $args
|
||||
* @return Page
|
||||
*/
|
||||
public function view(array $args)
|
||||
public function viewTopic(array $args)
|
||||
{
|
||||
$this->c->Lang->load('topic');
|
||||
|
||||
$user = $this->c->user;
|
||||
$vars = [
|
||||
':tid' => $args['id'],
|
||||
':uid' => $user->id,
|
||||
];
|
||||
|
||||
if ($user->isGuest) {
|
||||
if ($this->c->user->isGuest) {
|
||||
$sql = 'SELECT t.*, f.moderators, 0 AS is_subscribed
|
||||
FROM ::topics AS t
|
||||
INNER JOIN ::forums AS f ON f.id=t.forum_id
|
||||
|
@ -118,62 +129,88 @@ class Topic extends Page
|
|||
LEFT JOIN ::topic_subscriptions AS s ON (t.id=s.topic_id AND s.user_id=?i:uid)
|
||||
WHERE t.id=?i:tid AND t.moved_to IS NULL';
|
||||
}
|
||||
$topic = $this->c->DB->query($sql, $vars)->fetch();
|
||||
|
||||
$page = isset($args['page']) ? (int) $args['page'] : 1;
|
||||
|
||||
return $this->view($sql, $vars, $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготовка данных для шаблона
|
||||
* @param string $sql
|
||||
* @param array $vars
|
||||
* @param int|null $page
|
||||
* @return Page
|
||||
*/
|
||||
protected function view($sql, array $vars, $page)
|
||||
{
|
||||
$user = $this->c->user;
|
||||
|
||||
$vars[':uid'] = $user->id;
|
||||
|
||||
$topic = $this->c->DB->query($sql, $vars)->fetch();
|
||||
|
||||
// тема отсутствует или недоступна
|
||||
if (empty($topic)) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
|
||||
list($fTree, $fDesc, $fAsc) = $this->c->forums;
|
||||
|
||||
|
||||
// раздел отсутствует в доступных
|
||||
if (empty($fDesc[$topic['forum_id']])) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
if (null === $page) {
|
||||
$vars[':tid'] = $topic['id'];
|
||||
$sql = 'SELECT COUNT(id) FROM ::posts WHERE topic_id=?i:tid AND id<?i:pid';
|
||||
|
||||
$page = isset($args['page']) ? (int) $args['page'] : 1;
|
||||
$pages = ceil(( $topic['num_replies'] + 1) / $user->dispPosts);
|
||||
$num = 1 + $this->c->DB->query($sql, $vars)->fetchColumn();
|
||||
|
||||
$page = ceil($num / $user->dispPosts);
|
||||
}
|
||||
|
||||
$this->c->Lang->load('topic');
|
||||
|
||||
$pages = ceil(($topic['num_replies'] + 1) / $user->dispPosts);
|
||||
// попытка открыть страницу которой нет
|
||||
if ($page < 1 || $page > $pages) {
|
||||
return $this->c->Message->message('Bad request');
|
||||
}
|
||||
|
||||
$offset = ($page - 1) * $user->dispPosts;
|
||||
|
||||
$vars = [
|
||||
':tid' => $args['id'],
|
||||
':tid' => $topic['id'],
|
||||
':offset' => $offset,
|
||||
':rows' => $user->dispPosts,
|
||||
':rows' => $user->dispPosts,
|
||||
];
|
||||
$sql = 'SELECT id
|
||||
FROM ::posts
|
||||
WHERE topic_id=?i:tid
|
||||
ORDER BY id LIMIT ?i:offset, ?i:rows';
|
||||
|
||||
$ids = $this->c->DB->query($sql, $vars)->fetchAll(\PDO::FETCH_COLUMN);
|
||||
|
||||
// нарушена синхронизация количества сообщений в темах
|
||||
if (empty($ids)) {
|
||||
return $this->goToLast($args); //????
|
||||
return $this->goToLast($topic['id']);
|
||||
}
|
||||
|
||||
$moders = empty($topic['moderators']) ? [] : array_flip(unserialize($topic['moderators']));
|
||||
|
||||
$parent = isset($fDesc[$topic['forum_id']][0]) ? $fDesc[$topic['forum_id']][0] : 0;
|
||||
$perm = $fTree[$parent][$topic['forum_id']];
|
||||
|
||||
$newOn = null;
|
||||
if ($user->isAdmin) {
|
||||
$newPost = $this->c->Router->link('NewPost', ['id' => $args['id']]);
|
||||
$newOn = true;
|
||||
} elseif ($topic['closed'] == '1') {
|
||||
$newPost = false;
|
||||
$newOn = false;
|
||||
} elseif ($perm['post_replies'] === 1
|
||||
|| (null === $perm['post_replies'] && $user->gPostReplies == '1')
|
||||
|| ($user->isAdmMod && isset($moders[$user->id]))
|
||||
) {
|
||||
$newPost = $this->c->Router->link('NewPost', ['id' => $args['id']]);
|
||||
} else {
|
||||
$newPost = null;
|
||||
$newOn = true;
|
||||
}
|
||||
|
||||
// приклейка первого сообщения темы
|
||||
|
@ -188,6 +225,7 @@ class Topic extends Page
|
|||
$sql = 'SELECT id, message, poster, posted
|
||||
FROM ::warnings
|
||||
WHERE id IN (?ai:ids)';
|
||||
|
||||
$warnings = $this->c->DB->query($sql, $vars)->fetchAll(\PDO::FETCH_GROUP);
|
||||
|
||||
$vars = [
|
||||
|
@ -202,11 +240,33 @@ class Topic extends Page
|
|||
INNER JOIN ::users AS u ON u.id=p.poster_id
|
||||
INNER JOIN ::groups AS g ON g.g_id=u.group_id
|
||||
WHERE p.id IN (?ai:ids) ORDER BY p.id';
|
||||
|
||||
$stmt = $this->c->DB->query($sql, $vars);
|
||||
|
||||
// парсер и его настройка для сообщений
|
||||
$bbcodes = include $this->c->DIR_CONFIG . '/defaultBBCode.php';
|
||||
$smilies = $this->c->smilies;
|
||||
foreach ($smilies as &$cur) {
|
||||
$cur = $this->c->PUBLIC_URL . '/img/sm/' . $cur;
|
||||
}
|
||||
unset($cur);
|
||||
$bbInfo = $this->c->BBCODE_INFO;
|
||||
$bbWList = $this->config['p_message_bbcode'] == '1' ? null : [];
|
||||
$bbBList = $this->config['p_message_img_tag'] == '1' ? [] : ['img'];
|
||||
$parser = $this->c->Parser;
|
||||
$parser->setBBCodes($bbcodes)
|
||||
->setAttr('isSign', false)
|
||||
->setWhiteList($bbWList)
|
||||
->setBlackList($bbBList);
|
||||
if ($user->showSmilies == '1') {
|
||||
$parser->setSmilies($smilies)
|
||||
->setSmTpl($bbInfo['smTpl'], $bbInfo['smTplTag'], $bbInfo['smTplBl']);
|
||||
}
|
||||
|
||||
$genders = [1 => ' f-user-male', 2 => ' f-user-female'];
|
||||
$postCount = 0;
|
||||
$posts = [];
|
||||
$signs = [];
|
||||
$posters = [];
|
||||
while ($cur = $stmt->fetch()) {
|
||||
// данные по автору сообшения
|
||||
|
@ -215,6 +275,7 @@ class Topic extends Page
|
|||
} else {
|
||||
$post = [
|
||||
'poster' => $cur['username'],
|
||||
'poster_id' => $cur['poster_id'],
|
||||
'poster_title' => $this->censor($this->userGetTitle($cur)),
|
||||
'poster_avatar' => null,
|
||||
'poster_registered' => null,
|
||||
|
@ -251,6 +312,14 @@ class Topic extends Page
|
|||
$post['poster_online'] = ' f-user-online'; //????
|
||||
|
||||
$posters[$cur['poster_id']] = $post;
|
||||
|
||||
if ($this->config['o_signatures'] == '1'
|
||||
&& $cur['signature'] != ''
|
||||
&& $user->showSig == '1'
|
||||
&& ! isset($signs[$cur['poster_id']])
|
||||
) {
|
||||
$signs[$cur['poster_id']] = $cur['signature'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,6 +329,12 @@ class Topic extends Page
|
|||
$post['posted'] = $this->time($cur['posted']);
|
||||
$post['posted_utc'] = gmdate('Y-m-d\TH:i:s\Z', $cur['posted']);
|
||||
|
||||
$parser->parse($this->censor($cur['message']));
|
||||
if ($this->config['o_smilies'] == '1' && $user->showSmilies == '1' && $cur['hide_smilies'] == '0') {
|
||||
$parser->detectSmilies();
|
||||
}
|
||||
$post['message'] = $parser->getHtml();
|
||||
|
||||
// номер сообшения в теме
|
||||
if ($stickFP && $offset > 0 && $cur['id'] == $topic['first_post_id']) {
|
||||
$post['post_number'] = 1;
|
||||
|
@ -274,12 +349,22 @@ class Topic extends Page
|
|||
$controls['report'] = ['#', 'Report'];
|
||||
}
|
||||
if ($user->isAdmin
|
||||
|| ($user->isAdmMod && isset($moders[$user->id]))
|
||||
|| ($cur['poster_id'] == $user->id) //????
|
||||
|| ($user->isAdmMod && isset($moders[$user->id]) && ! in_array($cur['poster_id'], $this->c->admins))
|
||||
) {
|
||||
$controls['delete'] = ['#', 'Delete'];
|
||||
$controls['edit'] = ['#', 'Edit'];
|
||||
} elseif ($topic['closed'] != '1'
|
||||
&& $cur['poster_id'] == $user->id
|
||||
&& ($user->gDeleditInterval == '0' || $cur['edit_post'] == '1' || time() - $cur['posted'] < $user->gDeleditInterval)
|
||||
) {
|
||||
if (($cur['id'] == $topic['first_post_id'] && $user->gDeleteTopics == '1') || ($cur['id'] != $topic['first_post_id'] && $user->gDeletePosts == '1')) {
|
||||
$controls['delete'] = ['#', 'Delete'];
|
||||
}
|
||||
if ($user->gEditPosts == '1') {
|
||||
$controls['edit'] = ['#', 'Edit'];
|
||||
}
|
||||
}
|
||||
if ($newPost) {
|
||||
if ($newOn) {
|
||||
$controls['quote'] = ['#', 'Reply'];
|
||||
}
|
||||
|
||||
|
@ -288,50 +373,54 @@ class Topic extends Page
|
|||
$posts[] = $post;
|
||||
}
|
||||
|
||||
if ($signs) {
|
||||
// настройка парсера для подписей
|
||||
$bbWList = $this->config['p_sig_bbcode'] == '1' ? $bbInfo['forSign'] : [];
|
||||
$bbBList = $this->config['p_sig_img_tag'] == '1' ? [] : ['img'];
|
||||
$parser->setAttr('isSign', true)
|
||||
->setWhiteList($bbWList)
|
||||
->setBlackList($bbBList);
|
||||
|
||||
foreach ($signs as &$cur) {
|
||||
$parser->parse($this->censor($cur));
|
||||
if ($this->config['o_smilies_sig'] == '1' && $user->showSmilies == '1') {
|
||||
$parser->detectSmilies();
|
||||
}
|
||||
$cur = $parser->getHtml();
|
||||
}
|
||||
unset($cur);
|
||||
}
|
||||
|
||||
$topic['subject'] = $this->censor($topic['subject']);
|
||||
|
||||
$crumbs = [];
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Topic', ['id' => $args['id'], 'name' => $topic['subject']]),
|
||||
$topic['subject'],
|
||||
true,
|
||||
];
|
||||
$this->titles[] = $topic['subject'];
|
||||
|
||||
$id = $topic['forum_id'];
|
||||
$activ = null;
|
||||
while (true) {
|
||||
$name = $fDesc[$id]['forum_name'];
|
||||
$this->titles[] = $name;
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Forum', ['id' => $id, 'name' => $name]),
|
||||
$name,
|
||||
$activ,
|
||||
];
|
||||
$activ = null;
|
||||
if (! isset($fDesc[$id][0])) {
|
||||
break;
|
||||
}
|
||||
$id = $fDesc[$id][0];
|
||||
}
|
||||
$crumbs[] = [
|
||||
$this->c->Router->link('Index'),
|
||||
__('Index'),
|
||||
null,
|
||||
];
|
||||
$this->onlinePos = 'topic-' . $topic['id'];
|
||||
|
||||
$this->data = [
|
||||
'topic' => $topic,
|
||||
'posts' => $posts,
|
||||
'topic' => $topic,
|
||||
'posts' => $posts,
|
||||
'signs' => $signs,
|
||||
'warnings' => $warnings,
|
||||
'crumbs' => array_reverse($crumbs),
|
||||
'topicName' => $topic['subject'],
|
||||
'newPost' => $newPost,
|
||||
'stickFP' => $stickFP,
|
||||
'pages' => $this->c->Func->paginate($pages, $page, 'Topic', ['id' => $args['id'], 'name' => $topic['subject']]),
|
||||
'crumbs' => $this->getCrumbs(
|
||||
['Topic', ['id' => $topic['id'], 'name' => $topic['subject']]],
|
||||
[$fDesc, $topic['forum_id']]
|
||||
),
|
||||
'newPost' => $newOn ? $this->c->Router->link('NewPost', ['id' => $topic['id']]) : $newOn,
|
||||
'stickFP' => $stickFP,
|
||||
'pages' => $this->c->Func->paginate($pages, $page, 'Topic', ['id' => $topic['id'], 'name' => $topic['subject']]),
|
||||
'online' => $this->getUsersOnlineInfo(),
|
||||
'stats' => null,
|
||||
];
|
||||
|
||||
$this->canonical = $this->c->Router->link('Topic', ['id' => $args['id'], 'name' => $topic['subject'], 'page' => $page]);
|
||||
$this->canonical = $this->c->Router->link('Topic', ['id' => $topic['id'], 'name' => $topic['subject'], 'page' => $page]);
|
||||
|
||||
if ($this->config['o_topic_views'] == '1') {
|
||||
$vars = [
|
||||
':tid' => $topic['id'],
|
||||
];
|
||||
$sql = 'UPDATE ::topics SET num_views=num_views+1 WHERE id=?i:tid';
|
||||
|
||||
$this->c->DB->query($sql, $vars);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -47,10 +47,10 @@ trait UsersTrait
|
|||
$filetypes = array('jpg', 'gif', 'png');
|
||||
|
||||
foreach ($filetypes as $type) {
|
||||
$path = $this->c->DIR_PUBLIC . "/avatar/{$id}.{$type}";
|
||||
$path = $this->c->DIR_PUBLIC . "/{$this->config['o_avatars_dir']}/{$id}.{$type}";
|
||||
|
||||
if (file_exists($path) && getimagesize($path)) {
|
||||
return $this->c->PUBLIC_URL . "/avatar/{$id}.{$type}";
|
||||
return $this->c->PUBLIC_URL . "/{$this->config['o_avatars_dir']}/{$id}.{$type}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
510
app/config/defaultBBCode.php
Normal file
|
@ -0,0 +1,510 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
['tag' => 'ROOT',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
$body = '<p>' . $body . '</p>';
|
||||
|
||||
// Replace any breaks next to paragraphs so our replace below catches them
|
||||
$body = preg_replace('%(</?p>)(?:\s*?<br>){1,2}%', '$1', $body);
|
||||
$body = preg_replace('%(?:<br>\s*?){1,2}(</?p>)%', '$1', $body);
|
||||
|
||||
// Remove any empty paragraph tags (inserted via quotes/lists/code/etc) which should be stripped
|
||||
$body = str_replace('<p></p>', '', $body);
|
||||
|
||||
$body = preg_replace('%<br>\s*?<br>%', '</p><p>', $body);
|
||||
|
||||
$body = str_replace('<p><br>', '<br><p>', $body);
|
||||
$body = str_replace('<br></p>', '</p><br>', $body);
|
||||
$body = str_replace('<p></p>', '<br><br>', $body);
|
||||
|
||||
return $body;
|
||||
},
|
||||
],
|
||||
['tag' => 'code',
|
||||
'type' => 'block',
|
||||
'recursive' => true,
|
||||
'text only' => true,
|
||||
'pre' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$body = trim($body, "\n\r");
|
||||
$class = substr_count($body, "\n") > 28 ? ' class="vscroll"' : '';
|
||||
return '</p><div class="codebox"><pre' . $class . '><code>' . $body . '</code></pre></div><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<strong>' . $body . '</strong>';
|
||||
},
|
||||
],
|
||||
['tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<em>' . $body . '</em>';
|
||||
},
|
||||
],
|
||||
['tag' => 'em',
|
||||
'handler' => function($body) {
|
||||
return '<em>' . $body . '</em>';
|
||||
},
|
||||
],
|
||||
['tag' => 'u',
|
||||
'handler' => function($body) {
|
||||
return '<span class="bbu">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 's',
|
||||
'handler' => function($body) {
|
||||
return '<span class="bbs">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'del',
|
||||
'handler' => function($body) {
|
||||
return '<del>' . $body . '</del>';
|
||||
},
|
||||
],
|
||||
['tag' => 'ins',
|
||||
'handler' => function($body) {
|
||||
return '<ins>' . $body . '</ins>';
|
||||
},
|
||||
],
|
||||
['tag' => 'h',
|
||||
'type' => 'h',
|
||||
'handler' => function($body) {
|
||||
return '</p><h5>' . $body . '</h5><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'hr',
|
||||
'type' => 'block',
|
||||
'single' => true,
|
||||
'handler' => function() {
|
||||
return '</p><hr><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'color',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="color:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'colour',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="color:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'background',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="background-color:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'size',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[1-9]\d*(?:em|ex|pt|px|\%)?$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (is_numeric($attrs['Def'])) {
|
||||
$attrs['Def'] .= 'px';
|
||||
}
|
||||
return '<span style="font-size:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'right',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
return '</p><p style="text-align: right;">' . $body . '</p><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'center',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
return '</p><p style="text-align: center;">' . $body . '</p><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'justify',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
return '</p><p style="text-align: justify;">' . $body . '</p><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'mono',
|
||||
'handler' => function($body) {
|
||||
return '<code>' . $body . '</code>';
|
||||
},
|
||||
],
|
||||
['tag' => 'font',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[a-z\d, -]+$%i',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="font-family:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'email',
|
||||
'type' => 'email',
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[^\x00-\x1f\s]+?@[^\x00-\x1f\s]+$%',
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^[^\x00-\x1f\s]+?@[^\x00-\x1f\s]+$%D',
|
||||
'text only' => true,
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (empty($attrs['Def'])) {
|
||||
return '<a href="mailto:' . $body . '">' . $body . '</a>';
|
||||
} else {
|
||||
return '<a href="mailto:' . $attrs['Def'] . '">' . $body . '</a>';
|
||||
}
|
||||
},
|
||||
],
|
||||
['tag' => '*',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'parents' => ['list'],
|
||||
'auto' => true,
|
||||
'handler' => function($body) {
|
||||
return '<li><p>' . $body . '</p></li>';
|
||||
},
|
||||
],
|
||||
['tag' => 'list',
|
||||
'type' => 'list',
|
||||
'self nesting' => true,
|
||||
'tags only' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (!isset($attrs['Def'])) {
|
||||
$attrs['Def'] = '*';
|
||||
}
|
||||
|
||||
switch ($attrs['Def'][0]) {
|
||||
case 'a':
|
||||
return '</p><ol class="alpha">' . $body . '</ol><p>';
|
||||
case '1':
|
||||
return '</p><ol class="decimal">' . $body . '</ol><p>';
|
||||
default:
|
||||
return '</p><ul>' . $body . '</ul><p>';
|
||||
}
|
||||
},
|
||||
],
|
||||
['tag' => 'after',
|
||||
'type' => 'block',
|
||||
'single' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^\d+$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$arr = array();
|
||||
$sec = $attrs['Def'] % 60;
|
||||
$min = ($attrs['Def'] / 60) % 60;
|
||||
$hours = ($attrs['Def'] / 3600) % 24;
|
||||
$days = (int) ($attrs['Def'] / 86400);
|
||||
if ($days > 0) {
|
||||
$arr[] = $days . __('After time d');
|
||||
}
|
||||
if ($hours > 0) {
|
||||
$arr[] = $hours . __('After time H');
|
||||
}
|
||||
if ($min > 0) {
|
||||
$arr[] = (($min < 10) ? '0' . $min : $min) . __('After time i');
|
||||
}
|
||||
if ($sec > 0) {
|
||||
$arr[] = (($sec < 10) ? '0' . $sec : $sec) . __('After time s');
|
||||
}
|
||||
|
||||
$attr = __('After time') . ' ' . implode(' ', $arr);
|
||||
|
||||
return '<span style="color: #808080"><em>' . $attr . ':</em></span><br />';
|
||||
},
|
||||
],
|
||||
['tag' => 'quote',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (isset($attrs['Def'])) {
|
||||
$st = '</p><div class="quotebox"><cite>' . $attrs['Def'] . ' ' . __('wrote') . '</cite><blockquote><div><p>';
|
||||
} else {
|
||||
$st = '</p><div class="quotebox"><blockquote><div><p>';
|
||||
}
|
||||
|
||||
return $st . $body . '</p></div></blockquote></div><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'spoiler',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (isset($attrs['Def'])) {
|
||||
$st = '</p><div class="quotebox" style="padding: 0px;"><div onclick="var e,d,c=this.parentNode,a=c.getElementsByTagName(\'div\')[1],b=this.getElementsByTagName(\'span\')[0];if(a.style.display!=\'\'){while(c.parentNode&&(!d||!e||d==e)){e=d;d=(window.getComputedStyle?getComputedStyle(c, null):c.currentStyle)[\'backgroundColor\'];if(d==\'transparent\'||d==\'rgba(0, 0, 0, 0)\')d=e;c=c.parentNode;}a.style.display=\'\';a.style.backgroundColor=d;b.innerHTML=\'▲\';}else{a.style.display=\'none\';b.innerHTML=\'▼\';}" style="font-weight: bold; cursor: pointer; font-size: 0.9em;"><span style="padding: 0 5px;">▼</span>' . $attrs['Def'] . '</div><div style="padding: 6px; margin: 0; display: none;"><p>';
|
||||
} else {
|
||||
$st = '</p><div class="quotebox" style="padding: 0px;"><div onclick="var e,d,c=this.parentNode,a=c.getElementsByTagName(\'div\')[1],b=this.getElementsByTagName(\'span\')[0];if(a.style.display!=\'\'){while(c.parentNode&&(!d||!e||d==e)){e=d;d=(window.getComputedStyle?getComputedStyle(c, null):c.currentStyle)[\'backgroundColor\'];if(d==\'transparent\'||d==\'rgba(0, 0, 0, 0)\')d=e;c=c.parentNode;}a.style.display=\'\';a.style.backgroundColor=d;b.innerHTML=\'▲\';}else{a.style.display=\'none\';b.innerHTML=\'▼\';}" style="font-weight: bold; cursor: pointer; font-size: 0.9em;"><span style="padding: 0 5px;">▼</span>' . __('Hidden text') . '</div><div style="padding: 6px; margin: 0; display: none;"><p>';
|
||||
}
|
||||
|
||||
return $st . $body . '</p></div></div><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'img',
|
||||
'type' => 'img',
|
||||
'parents' => ['inline', 'block', 'url'],
|
||||
'text only' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'body format' => '%^(?:(?:ht|f)tps?://[^\x00-\x1f\s<"]+|data:image/[a-z]+;base64,(?:[a-zA-Z\d/\+\=]+))$%D'
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^(?:(?:ht|f)tps?://[^\x00-\x1f\s<"]+|data:image/[a-z]+;base64,(?:[a-zA-Z\d/\+\=]+))$%D'
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (! isset($attrs['Def'])) {
|
||||
$attrs['Def'] = (substr($body, 0, 11) === 'data:image/') ? 'base64' : basename($body);
|
||||
}
|
||||
|
||||
// тег в подписи
|
||||
if ($parser->attr('isSign')) {
|
||||
if ($parser->attr('showImgSign')) {
|
||||
return '<img src="' . $body . '" alt="' . $attrs['Def'] . '" class="sigimage" />';
|
||||
}
|
||||
} else {
|
||||
// тег в теле сообщения
|
||||
if ($parser->attr('showImg')) {
|
||||
return '<span class="postimg"><img src="' . $body . '" alt="' . $attrs['Def'] . '" /></span>';
|
||||
}
|
||||
}
|
||||
|
||||
return '<a href="' . $body . '" rel="nofollow"><' . __('Image link') . ' - ' . $attrs['Def'] . '></a>';
|
||||
},
|
||||
],
|
||||
['tag' => 'url',
|
||||
'type' => 'url',
|
||||
'parents' => ['inline', 'block'],
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[^\x00-\x1f]+$%',
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^[^\x00-\x1f]+$%D',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (isset($attrs['Def'])) {
|
||||
$url = $attrs['Def'];
|
||||
} else {
|
||||
$url = $body;
|
||||
// возможно внутри была картинка, которая отображается как ссылка
|
||||
if (preg_match('%^<a href=".++(?<=</a>)$%D', $url)) {
|
||||
return $url;
|
||||
}
|
||||
// возможно внутри картинка
|
||||
if (preg_match('%<img src="([^"]+)"%', $url, $match)) {
|
||||
$url = $match[1];
|
||||
}
|
||||
}
|
||||
|
||||
$fUrl = str_replace(array(' ', '\'', '`', '"'), array('%20', '', '', ''), $url);
|
||||
|
||||
if (strpos($url, 'www.') === 0) {
|
||||
$fUrl = 'http://'.$fUrl;
|
||||
} else if (strpos($url, 'ftp.') === 0) {
|
||||
$fUrl = 'ftp://'.$fUrl;
|
||||
} else if (strpos($url, '/') === 0) {
|
||||
$fUrl = $parser->attr('baseUrl') . $fUrl;
|
||||
} else if (!preg_match('%^([a-z0-9]{3,6})://%', $url)) {
|
||||
$fUrl = 'http://'.$fUrl;
|
||||
}
|
||||
|
||||
if ($url === $body) {
|
||||
$url = htmlspecialchars_decode($url, ENT_QUOTES);
|
||||
$url = mb_strlen($url, 'UTF-8') > 55 ? mb_substr($url, 0, 39, 'UTF-8') . ' … ' . mb_substr($url, -10, null, 'UTF-8') : $url;
|
||||
$body = $parser->e($url);
|
||||
}
|
||||
|
||||
return '<a href="' . $fUrl . '" rel="nofollow">' . $body . '</a>';
|
||||
},
|
||||
],
|
||||
['tag' => 'table',
|
||||
'type' => 'table',
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'align' => true,
|
||||
'background' => true,
|
||||
'bgcolor' => true,
|
||||
'border' => true,
|
||||
'bordercolor' => true,
|
||||
'cellpadding' => true,
|
||||
'cellspacing' => true,
|
||||
'frame' => true,
|
||||
'rules' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '</p><table' . $attr . '>' . $body . '</table><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'caption',
|
||||
'type' => 'block',
|
||||
'parents' => ['table'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<caption' . $attr . '><p>' . $body . '</p></caption>';
|
||||
},
|
||||
],
|
||||
['tag' => 'thead',
|
||||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<thead' . $attr . '>' . $body . '</thead>';
|
||||
},
|
||||
],
|
||||
['tag' => 'tbody',
|
||||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<tbody' . $attr . '>' . $body . '</tbody>';
|
||||
},
|
||||
],
|
||||
['tag' => 'tfoot',
|
||||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<tfoot' . $attr . '>' . $body . '</tfoot>';
|
||||
},
|
||||
],
|
||||
['tag' => 'tr',
|
||||
'type' => 'tr',
|
||||
'parents' => ['table', 't'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<tr' . $attr . '>' . $body . '</tr>';
|
||||
},
|
||||
],
|
||||
['tag' => 'th',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'colspan' => true,
|
||||
'rowspan' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<th' . $attr . '><p>' . $body . '</p></th>';
|
||||
},
|
||||
],
|
||||
['tag' => 'td',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'colspan' => true,
|
||||
'rowspan' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<td' . $attr . '><p>' . $body . '</p></td>';
|
||||
},
|
||||
],
|
||||
];
|
|
@ -24,12 +24,6 @@ msgstr "Board is empty."
|
|||
msgid "Newest user"
|
||||
msgstr "Newest registered user:"
|
||||
|
||||
msgid "Users online"
|
||||
msgstr "Registered users online:"
|
||||
|
||||
msgid "Guests online"
|
||||
msgstr "guests:"
|
||||
|
||||
msgid "No of users"
|
||||
msgstr "Total number of registered users:"
|
||||
|
||||
|
@ -39,10 +33,10 @@ msgstr "Total number of topics:"
|
|||
msgid "No of posts"
|
||||
msgstr "Total number of posts:"
|
||||
|
||||
msgid "Online"
|
||||
msgid "Online users"
|
||||
msgstr "Online:"
|
||||
|
||||
msgid "Board info"
|
||||
msgid "Stats info"
|
||||
msgstr "Board information"
|
||||
|
||||
msgid "Board stats"
|
||||
|
@ -53,3 +47,6 @@ msgstr "Maximum online users (%1$s) was be there %2$s"
|
|||
|
||||
msgid "User info"
|
||||
msgstr "User information"
|
||||
|
||||
msgid "Visitors online"
|
||||
msgstr "Registered users online: <strong>%1$s</strong>, guests: <strong>%2$s</strong>."
|
||||
|
|
|
@ -95,8 +95,14 @@ msgstr "Warnings:"
|
|||
msgid "Reply"
|
||||
msgstr "Reply"
|
||||
|
||||
msgid "Users online"
|
||||
msgstr "Registered users online in this topic: %s"
|
||||
msgid "User info"
|
||||
msgstr "User information"
|
||||
|
||||
msgid "Guests online"
|
||||
msgstr "guests: %s"
|
||||
msgid "Visitors online"
|
||||
msgstr "Registered users online in this topic: <strong>%1$s</strong>, guests: <strong>%2$s</strong>."
|
||||
|
||||
msgid "Online users"
|
||||
msgstr "Online:"
|
||||
|
||||
msgid "Stats info"
|
||||
msgstr "Topic information"
|
||||
|
|
|
@ -24,12 +24,6 @@ msgstr "Форум пуст."
|
|||
msgid "Newest user"
|
||||
msgstr "Новичок:"
|
||||
|
||||
msgid "Users online"
|
||||
msgstr "Сейчас пользователей:"
|
||||
|
||||
msgid "Guests online"
|
||||
msgstr "гостей:"
|
||||
|
||||
msgid "No of users"
|
||||
msgstr "Всего пользователей:"
|
||||
|
||||
|
@ -39,10 +33,10 @@ msgstr "Всего тем:"
|
|||
msgid "No of posts"
|
||||
msgstr "Всего сообщений:"
|
||||
|
||||
msgid "Online"
|
||||
msgid "Online users"
|
||||
msgstr "Активны:"
|
||||
|
||||
msgid "Board info"
|
||||
msgid "Stats info"
|
||||
msgstr "Информация о форуме"
|
||||
|
||||
msgid "Board stats"
|
||||
|
@ -53,3 +47,6 @@ msgstr "Больше всего онлайн посетителей (%1$s) зд
|
|||
|
||||
msgid "User info"
|
||||
msgstr "Информация о пользователях"
|
||||
|
||||
msgid "Visitors online"
|
||||
msgstr "Сейчас пользователей: <strong>%1$s</strong>, гостей: <strong>%2$s</strong>."
|
||||
|
|
|
@ -96,8 +96,14 @@ msgstr "Предупреждений:"
|
|||
msgid "Reply"
|
||||
msgstr "Ответить"
|
||||
|
||||
msgid "Users online"
|
||||
msgstr "Сейчас в этой теме пользователей: %s"
|
||||
msgid "User info"
|
||||
msgstr "Информация о пользователях"
|
||||
|
||||
msgid "Guests online"
|
||||
msgstr "гостей: %s"
|
||||
msgid "Visitors online"
|
||||
msgstr "Сейчас в этой теме пользователей: <strong>%1$s</strong>, гостей: <strong>%2$s</strong>."
|
||||
|
||||
msgid "Online users"
|
||||
msgstr "Активны:"
|
||||
|
||||
msgid "Stats info"
|
||||
msgstr "Информация о теме"
|
||||
|
|
|
@ -22,38 +22,4 @@
|
|||
<h2>{!! __('Empty board') !!}</h2>
|
||||
</section>
|
||||
@endif
|
||||
<section class="f-stats">
|
||||
<h2>{!! __('Board info') !!}</h2>
|
||||
<div class="clearfix">
|
||||
<dl class="right">
|
||||
<dt>{!! __('Board stats') !!}</dt>
|
||||
<dd>{!! __('No of users') !!} <strong>{!! $stats['total_users'] !!}</strong></dd>
|
||||
<dd>{!! __('No of topics') !!} <strong>{!! $stats['total_topics'] !!}</strong></dd>
|
||||
<dd>{!! __('No of posts') !!} <strong>{!! $stats['total_posts'] !!}</strong></dd>
|
||||
</dl>
|
||||
<dl class="left">
|
||||
<dt>{!! __('User info') !!}</dt>
|
||||
@if(is_string($stats['newest_user']))
|
||||
<dd>{!! __('Newest user') !!} {{ $stats['newest_user'] }}</dd>
|
||||
@else
|
||||
<dd>{!! __('Newest user') !!} <a href="{!! $stats['newest_user'][0] !!}">{{ $stats['newest_user'][1] }}</a></dd>
|
||||
@endif
|
||||
@if($online)
|
||||
<dd>{!! __('Users online') !!} <strong>{!! $online['number_of_users'] !!}</strong>, {!! __('Guests online') !!} <strong>{!! $online['number_of_guests'] !!}</strong>.</dd>
|
||||
<dd>{!! __('Most online', $online['max'], $online['max_time']) !!}</dd>
|
||||
@endif
|
||||
</dl>
|
||||
@if($online && $online['list'])
|
||||
<dl class="f-inline f-onlinelist"><!-- inline -->
|
||||
<dt>{!! __('Online') !!}</dt>
|
||||
@foreach($online['list'] as $cur)
|
||||
@if(is_string($cur))
|
||||
<dd>{{ $cur }}</dd>
|
||||
@else
|
||||
<dd><a href="{!! $cur[0] !!}">{{ $cur[1] }}</a></dd>
|
||||
@endif
|
||||
@endforeach
|
||||
</dl><!-- endinline -->
|
||||
@endif
|
||||
</div>
|
||||
</section>
|
||||
@include('layouts/stats')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{!! __('lang_identifier') !!} dir="{!! __('lang_direction') !!}">
|
||||
<html lang="{!! __('lang_identifier') !!}" dir="{!! __('lang_direction') !!}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
|
39
app/templates/layouts/stats.tpl
Normal file
|
@ -0,0 +1,39 @@
|
|||
<section class="f-stats">
|
||||
<h2>{!! __('Stats info') !!}</h2>
|
||||
<div class="clearfix">
|
||||
@if($stats)
|
||||
<dl class="right">
|
||||
<dt>{!! __('Board stats') !!}</dt>
|
||||
<dd>{!! __('No of users') !!} <strong>{!! $stats['total_users'] !!}</strong></dd>
|
||||
<dd>{!! __('No of topics') !!} <strong>{!! $stats['total_topics'] !!}</strong></dd>
|
||||
<dd>{!! __('No of posts') !!} <strong>{!! $stats['total_posts'] !!}</strong></dd>
|
||||
</dl>
|
||||
@endif
|
||||
<dl class="left">
|
||||
<dt>{!! __('User info') !!}</dt>
|
||||
@if($stats && is_string($stats['newest_user']))
|
||||
<dd>{!! __('Newest user') !!} {{ $stats['newest_user'] }}</dd>
|
||||
@elseif($stats)
|
||||
<dd>{!! __('Newest user') !!} <a href="{!! $stats['newest_user'][0] !!}">{{ $stats['newest_user'][1] }}</a></dd>
|
||||
@endif
|
||||
@if($online)
|
||||
<dd>{!! __('Visitors online', $online['number_of_users'], $online['number_of_guests']) !!}</dd>
|
||||
@endif
|
||||
@if($stats)
|
||||
<dd>{!! __('Most online', $online['max'], $online['max_time']) !!}</dd>
|
||||
@endif
|
||||
</dl>
|
||||
@if($online && $online['list'])
|
||||
<dl class="f-inline f-onlinelist"><!-- inline -->
|
||||
<dt>{!! __('Online users') !!}</dt>
|
||||
@foreach($online['list'] as $cur)
|
||||
@if(is_string($cur))
|
||||
<dd>{{ $cur }}</dd>
|
||||
@else
|
||||
<dd><a href="{!! $cur[0] !!}">{{ $cur[1] }}</a></dd>
|
||||
@endif
|
||||
@endforeach
|
||||
</dl><!-- endinline -->
|
||||
@endif
|
||||
</div>
|
||||
</section>
|
|
@ -48,14 +48,14 @@
|
|||
@endif
|
||||
</div>
|
||||
<section class="f-main f-topic">
|
||||
<h2>{{ $topicName }}</h2>
|
||||
<h2>{{ $topic['subject'] }}</h2>
|
||||
@foreach($posts as $post)
|
||||
<article id="p{!! $post['id'] !!}" class="f-post{!! $post['poster_gender'].$post['poster_online'] !!} clearfix">
|
||||
<div class="f-post-header clearfix">
|
||||
<h3>{{ $topicName }} - #{!! $post['post_number'] !!}</h3>
|
||||
<header class="f-post-header clearfix">
|
||||
<h3>{{ $topic['subject'] }} - #{!! $post['post_number'] !!}</h3>
|
||||
<span class="left"><time datetime="{{ $post['posted_utc'] }}">{{ $post['posted'] }}</time></span>
|
||||
<span class="right"><a href="{!! $post['link'] !!}" rel="bookmark">#{!! $post['post_number'] !!}</a></span>
|
||||
</div>
|
||||
</header>
|
||||
<div class="f-post-body clearfix">
|
||||
<address class="f-post-left clearfix">
|
||||
<ul class="f-user-info">
|
||||
|
@ -84,9 +84,17 @@
|
|||
</ul>
|
||||
@endif
|
||||
</address>
|
||||
|
||||
<div class="f-post-right f-post-main">
|
||||
{!! $post['message'] !!}
|
||||
</div>
|
||||
@if(isset($signs[$post['poster_id']]))
|
||||
<div class="f-post-right f-post-signature">
|
||||
<hr>
|
||||
{!! $signs[$post['poster_id']] !!}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="f-post-footer clearfix">
|
||||
<footer class="f-post-footer clearfix">
|
||||
<div class="f-post-left">
|
||||
<span></span>
|
||||
</div>
|
||||
|
@ -99,7 +107,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</footer>
|
||||
</article>
|
||||
@endforeach
|
||||
</section>
|
||||
|
@ -112,3 +120,6 @@
|
|||
@endif
|
||||
@yield('crumbs')
|
||||
</div>
|
||||
@if($online)
|
||||
@include('layouts/stats')
|
||||
@endif
|
|
@ -18,6 +18,7 @@
|
|||
},
|
||||
"require": {
|
||||
"php": ">=5.6.0",
|
||||
"artoodetoo/dirk": "dev-master"
|
||||
"artoodetoo/dirk": "dev-master",
|
||||
"MioVisman/Parserus": "^0.9.1"
|
||||
}
|
||||
}
|
||||
|
|
46
composer.lock
generated
|
@ -4,8 +4,8 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "ad22a23d7b225fa300553d8d0dcdaeb9",
|
||||
"content-hash": "2eea8744cdbc34c8408e6d137176a8df",
|
||||
"hash": "f222f403c8d48f00cb5e3e37f680ebcb",
|
||||
"content-hash": "b8c1ffae094a89502ad8a3c60385d4b8",
|
||||
"packages": [
|
||||
{
|
||||
"name": "artoodetoo/dirk",
|
||||
|
@ -52,6 +52,48 @@
|
|||
"views"
|
||||
],
|
||||
"time": "2017-01-10 21:38:22"
|
||||
},
|
||||
{
|
||||
"name": "miovisman/parserus",
|
||||
"version": "0.9.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MioVisman/Parserus.git",
|
||||
"reference": "d039178d46c989ebb8eb89970b52eb6ce927c817"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MioVisman/Parserus/zipball/d039178d46c989ebb8eb89970b52eb6ce927c817",
|
||||
"reference": "d039178d46c989ebb8eb89970b52eb6ce927c817",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Parserus": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Visman",
|
||||
"email": "mio.visman@yandex.ru",
|
||||
"homepage": "https://github.com/MioVisman"
|
||||
}
|
||||
],
|
||||
"description": "BBCode parser.",
|
||||
"homepage": "https://github.com/MioVisman/Parserus",
|
||||
"keywords": [
|
||||
"bbcode",
|
||||
"parser"
|
||||
],
|
||||
"time": "2016-11-26 06:56:51"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
|
|
@ -4,7 +4,7 @@ AddDefaultCharset UTF-8
|
|||
RewriteEngine On
|
||||
#RewriteBase /
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
#RewriteCond %{REQUEST_FILENAME} !-d
|
||||
#RewriteCond %{REQUEST_URI} !/public/.*\.\w+$
|
||||
RewriteCond %{REQUEST_URI} !favicon\.ico
|
||||
RewriteRule . index.php [L]
|
||||
|
|
BIN
public/img/sm/big_smile.png
Normal file
After Width: | Height: | Size: 373 B |
BIN
public/img/sm/cool.png
Normal file
After Width: | Height: | Size: 380 B |
BIN
public/img/sm/hmm.png
Normal file
After Width: | Height: | Size: 422 B |
BIN
public/img/sm/lol.png
Normal file
After Width: | Height: | Size: 364 B |
BIN
public/img/sm/mad.png
Normal file
After Width: | Height: | Size: 409 B |
BIN
public/img/sm/neutral.png
Normal file
After Width: | Height: | Size: 415 B |
BIN
public/img/sm/roll.png
Normal file
After Width: | Height: | Size: 386 B |
BIN
public/img/sm/sad.png
Normal file
After Width: | Height: | Size: 420 B |
BIN
public/img/sm/smile.png
Normal file
After Width: | Height: | Size: 426 B |
BIN
public/img/sm/tongue.png
Normal file
After Width: | Height: | Size: 416 B |
BIN
public/img/sm/wink.png
Normal file
After Width: | Height: | Size: 428 B |
BIN
public/img/sm/yikes.png
Normal file
After Width: | Height: | Size: 406 B |
|
@ -1215,6 +1215,11 @@ li + li .f-btn {
|
|||
clear: left;
|
||||
}
|
||||
|
||||
.f-post-signature {
|
||||
font-size: 0.875rem;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 50rem) {
|
||||
.f-post {
|
||||
background-color: #F8F4E3;
|
||||
|
|
1
vendor/composer/autoload_namespaces.php
vendored
|
@ -6,4 +6,5 @@ $vendorDir = dirname(dirname(__FILE__));
|
|||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Parserus' => array($vendorDir . '/miovisman/parserus'),
|
||||
);
|
||||
|
|
11
vendor/composer/autoload_static.php
vendored
|
@ -28,11 +28,22 @@ class ComposerStaticInit90ad93c7251d4f60daa9e545879c49e7
|
|||
),
|
||||
);
|
||||
|
||||
public static $prefixesPsr0 = array (
|
||||
'P' =>
|
||||
array (
|
||||
'Parserus' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/miovisman/parserus',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit90ad93c7251d4f60daa9e545879c49e7::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit90ad93c7251d4f60daa9e545879c49e7::$prefixDirsPsr4;
|
||||
$loader->prefixesPsr0 = ComposerStaticInit90ad93c7251d4f60daa9e545879c49e7::$prefixesPsr0;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
|
44
vendor/composer/installed.json
vendored
|
@ -46,5 +46,49 @@
|
|||
"templating",
|
||||
"views"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "miovisman/parserus",
|
||||
"version": "0.9.1",
|
||||
"version_normalized": "0.9.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MioVisman/Parserus.git",
|
||||
"reference": "d039178d46c989ebb8eb89970b52eb6ce927c817"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MioVisman/Parserus/zipball/d039178d46c989ebb8eb89970b52eb6ce927c817",
|
||||
"reference": "d039178d46c989ebb8eb89970b52eb6ce927c817",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"time": "2016-11-26 06:56:51",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Parserus": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Visman",
|
||||
"email": "mio.visman@yandex.ru",
|
||||
"homepage": "https://github.com/MioVisman"
|
||||
}
|
||||
],
|
||||
"description": "BBCode parser.",
|
||||
"homepage": "https://github.com/MioVisman/Parserus",
|
||||
"keywords": [
|
||||
"bbcode",
|
||||
"parser"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
21
vendor/miovisman/parserus/LICENSE
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2016 Visman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
1222
vendor/miovisman/parserus/Parserus.php
vendored
Normal file
40
vendor/miovisman/parserus/README.md
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Parserus
|
||||
|
||||
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
|
||||
|
||||
BBCode parser.
|
||||
|
||||
## Requirements
|
||||
|
||||
* PHP 5.4.0
|
||||
|
||||
## Installation
|
||||
|
||||
Include `Parserus.php` or install [the composer package](https://packagist.org/packages/MioVisman/Parserus).
|
||||
|
||||
## Example
|
||||
|
||||
``` php
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->addBBCode([
|
||||
'tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<b>' . $body . '</b>';
|
||||
}
|
||||
])->addBBcode([
|
||||
'tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
])->parse("[i]Hello\n[b]World[/b]![/i]")
|
||||
->getHTML();
|
||||
|
||||
#output: <i>Hello<br><b>World</b>!</i>
|
||||
```
|
||||
|
||||
More examples in [the wiki](https://github.com/MioVisman/Parserus/wiki).
|
||||
|
||||
## License
|
||||
|
||||
This project is under MIT license. Please see the [license file](LICENSE) for details.
|
21
vendor/miovisman/parserus/composer.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "miovisman/parserus",
|
||||
"description": "BBCode parser.",
|
||||
"keywords": ["bbcode", "parser"],
|
||||
"homepage": "https://github.com/MioVisman/Parserus",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Visman",
|
||||
"email": "mio.visman@yandex.ru",
|
||||
"homepage": "https://github.com/MioVisman"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {"Parserus": ""}
|
||||
}
|
||||
}
|
20
vendor/miovisman/parserus/examples/_first.php
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->addBBCode([
|
||||
'tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<b>' . $body . '</b>';
|
||||
}
|
||||
])->addBBcode([
|
||||
'tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
])->parse("[i]Hello\n[b]World[/b]![/i]")
|
||||
->getHTML();
|
||||
|
||||
#output: <i>Hello<br><b>World</b>!</i>
|
20
vendor/miovisman/parserus/examples/_second.php
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus(ENT_XHTML);
|
||||
|
||||
echo $parser->addBBCode([
|
||||
'tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<b>' . $body . '</b>';
|
||||
}
|
||||
])->addBBcode([
|
||||
'tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
])->parse("[i]Hello\n[b]World[/b]![/i]")
|
||||
->getHTML();
|
||||
|
||||
#output: <i>Hello<br /><b>World</b>!</i>
|
20
vendor/miovisman/parserus/examples/_third.php
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->addBBCode([
|
||||
'tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<b>' . $body . '</b>';
|
||||
}
|
||||
])->addBBcode([
|
||||
'tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
])->parse("[i]\nHello\n[b]\nWorld!")
|
||||
->getHTML();
|
||||
|
||||
#output: <i>Hello<br><b>World!</b></i>
|
50
vendor/miovisman/parserus/examples/attr.php
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->addBBCode([
|
||||
'tag' => 'after',
|
||||
'type' => 'block',
|
||||
'single' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^\d+$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
$lang = $parser->attr('lang');
|
||||
$arr = array();
|
||||
$sec = $attrs['Def'] % 60;
|
||||
$min = ($attrs['Def'] / 60) % 60;
|
||||
$hours = ($attrs['Def'] / 3600) % 24;
|
||||
$days = (int) ($attrs['Def'] / 86400);
|
||||
if ($days > 0) {
|
||||
$arr[] = $days . $lang['After time d'];
|
||||
}
|
||||
if ($hours > 0) {
|
||||
$arr[] = $hours . $lang['After time H'];
|
||||
}
|
||||
if ($min > 0) {
|
||||
$arr[] = (($min < 10) ? '0' . $min : $min) . $lang['After time i'];
|
||||
}
|
||||
if ($sec > 0) {
|
||||
$arr[] = (($sec < 10) ? '0' . $sec : $sec) . $lang['After time s'];
|
||||
}
|
||||
|
||||
$attr = $lang['After time'] . ' ' . implode(' ', $arr);
|
||||
|
||||
return '<span style="color: #808080"><em>' . $attr . ':</em></span><br>';
|
||||
},
|
||||
])->setAttr('lang', [
|
||||
'After time' => 'Added later',
|
||||
'After time s' => ' s',
|
||||
'After time i' => ' min',
|
||||
'After time H' => ' h',
|
||||
'After time d' => ' d',
|
||||
])->parse('[after=10123]')
|
||||
->getHTML();
|
||||
|
||||
|
||||
#output: <span style="color: #808080"><em>Added later 2 h 48 min 43 s:</em></span><br>
|
588
vendor/miovisman/parserus/examples/bbcodes_test.php
vendored
Normal file
|
@ -0,0 +1,588 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
# example on the basis of (partially) bb-codes from FluxBB/PunBB parsers
|
||||
# пример на основании (частично) bb-кодов из парсеров FluxBB/PunBB
|
||||
|
||||
$bbcodes = [
|
||||
['tag' => 'ROOT',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
$body = '<p>' . $body . '</p>';
|
||||
|
||||
// Replace any breaks next to paragraphs so our replace below catches them
|
||||
$body = preg_replace('%(</?p>)(?:\s*?<br />){1,2}%', '$1', $body);
|
||||
$body = preg_replace('%(?:<br />\s*?){1,2}(</?p>)%', '$1', $body);
|
||||
|
||||
// Remove any empty paragraph tags (inserted via quotes/lists/code/etc) which should be stripped
|
||||
$body = str_replace('<p></p>', '', $body);
|
||||
|
||||
$body = preg_replace('%<br />\s*?<br />%', '</p><p>', $body);
|
||||
|
||||
$body = str_replace('<p><br />', '<br /><p>', $body);
|
||||
$body = str_replace('<br /></p>', '</p><br />', $body);
|
||||
$body = str_replace('<p></p>', '<br /><br />', $body);
|
||||
|
||||
return $body;
|
||||
},
|
||||
],
|
||||
['tag' => 'code',
|
||||
'type' => 'block',
|
||||
'recursive' => true,
|
||||
'text only' => true,
|
||||
'pre' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$body = trim($body, "\n\r");
|
||||
$class = substr_count($body, "\n") > 28 ? ' class="vscroll"' : '';
|
||||
return '</p><div class="codebox"><pre' . $class . '><code>' . $body . '</code></pre></div><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<strong>' . $body . '</strong>';
|
||||
},
|
||||
],
|
||||
['tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<em>' . $body . '</em>';
|
||||
},
|
||||
],
|
||||
['tag' => 'em',
|
||||
'handler' => function($body) {
|
||||
return '<em>' . $body . '</em>';
|
||||
},
|
||||
],
|
||||
['tag' => 'u',
|
||||
'handler' => function($body) {
|
||||
return '<span class="bbu">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 's',
|
||||
'handler' => function($body) {
|
||||
return '<span class="bbs">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'del',
|
||||
'handler' => function($body) {
|
||||
return '<del>' . $body . '</del>';
|
||||
},
|
||||
],
|
||||
['tag' => 'ins',
|
||||
'handler' => function($body) {
|
||||
return '<ins>' . $body . '</ins>';
|
||||
},
|
||||
],
|
||||
['tag' => 'h',
|
||||
'type' => 'h',
|
||||
'handler' => function($body) {
|
||||
return '</p><h5>' . $body . '</h5><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'hr',
|
||||
'type' => 'block',
|
||||
'single' => true,
|
||||
'handler' => function() {
|
||||
return '</p><hr /><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'color',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="color:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'colour',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="color:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'background',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="background-color:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'size',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[1-9]\d*(?:em|ex|pt|px|\%)?$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (is_numeric($attrs['Def'])) {
|
||||
$attrs['Def'] .= 'px';
|
||||
}
|
||||
return '<span style="font-size:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'right',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
return '</p><p style="text-align: right;">' . $body . '</p><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'center',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
return '</p><p style="text-align: center;">' . $body . '</p><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'justify',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
return '</p><p style="text-align: justify;">' . $body . '</p><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'mono',
|
||||
'handler' => function($body) {
|
||||
return '<code>' . $body . '</code>';
|
||||
},
|
||||
],
|
||||
['tag' => 'font',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[a-z\d, -]+$%i',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="font-family:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'email',
|
||||
'type' => 'email',
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[^\x00-\x1f\s]+?@[^\x00-\x1f\s]+$%',
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^[^\x00-\x1f\s]+?@[^\x00-\x1f\s]+$%D',
|
||||
'text only' => true,
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (empty($attrs['Def'])) {
|
||||
return '<a href="mailto:' . $body . '">' . $body . '</a>';
|
||||
} else {
|
||||
return '<a href="mailto:' . $attrs['Def'] . '">' . $body . '</a>';
|
||||
}
|
||||
},
|
||||
],
|
||||
['tag' => '*',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'parents' => ['list'],
|
||||
'auto' => true,
|
||||
'handler' => function($body) {
|
||||
return '<li><p>' . $body . '</p></li>';
|
||||
},
|
||||
],
|
||||
['tag' => 'list',
|
||||
'type' => 'list',
|
||||
'self nesting' => true,
|
||||
'tags only' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (!isset($attrs['Def'])) {
|
||||
$attrs['Def'] = '*';
|
||||
}
|
||||
|
||||
switch ($attrs['Def'][0]) {
|
||||
case 'a':
|
||||
return '</p><ol class="alpha">' . $body . '</ol><p>';
|
||||
case '1':
|
||||
return '</p><ol class="decimal">' . $body . '</ol><p>';
|
||||
default:
|
||||
return '</p><ul>' . $body . '</ul><p>';
|
||||
}
|
||||
},
|
||||
],
|
||||
['tag' => 'after',
|
||||
'type' => 'block',
|
||||
'single' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^\d+$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
$lang = $parser->attr('lang');
|
||||
$arr = array();
|
||||
$sec = $attrs['Def'] % 60;
|
||||
$min = ($attrs['Def'] / 60) % 60;
|
||||
$hours = ($attrs['Def'] / 3600) % 24;
|
||||
$days = (int) ($attrs['Def'] / 86400);
|
||||
if ($days > 0) {
|
||||
$arr[] = $days . $lang['After time d'];
|
||||
}
|
||||
if ($hours > 0) {
|
||||
$arr[] = $hours . $lang['After time H'];
|
||||
}
|
||||
if ($min > 0) {
|
||||
$arr[] = (($min < 10) ? '0' . $min : $min) . $lang['After time i'];
|
||||
}
|
||||
if ($sec > 0) {
|
||||
$arr[] = (($sec < 10) ? '0' . $sec : $sec) . $lang['After time s'];
|
||||
}
|
||||
|
||||
$attr = $lang['After time'] . ' ' . implode(' ', $arr);
|
||||
|
||||
return '<span style="color: #808080"><em>' . $attr . ':</em></span><br />';
|
||||
},
|
||||
],
|
||||
['tag' => 'quote',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (isset($attrs['Def'])) {
|
||||
$lang = $parser->attr('lang');
|
||||
$st = '</p><div class="quotebox"><cite>' . $attrs['Def'] . ' ' . $lang['wrote'] . '</cite><blockquote><div><p>';
|
||||
} else {
|
||||
$st = '</p><div class="quotebox"><blockquote><div><p>';
|
||||
}
|
||||
|
||||
return $st . $body . '</p></div></blockquote></div><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'spoiler',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (isset($attrs['Def'])) {
|
||||
$st = '</p><div class="quotebox" style="padding: 0px;"><div onclick="var e,d,c=this.parentNode,a=c.getElementsByTagName(\'div\')[1],b=this.getElementsByTagName(\'span\')[0];if(a.style.display!=\'\'){while(c.parentNode&&(!d||!e||d==e)){e=d;d=(window.getComputedStyle?getComputedStyle(c, null):c.currentStyle)[\'backgroundColor\'];if(d==\'transparent\'||d==\'rgba(0, 0, 0, 0)\')d=e;c=c.parentNode;}a.style.display=\'\';a.style.backgroundColor=d;b.innerHTML=\'▲\';}else{a.style.display=\'none\';b.innerHTML=\'▼\';}" style="font-weight: bold; cursor: pointer; font-size: 0.9em;"><span style="padding: 0 5px;">▼</span>' . $attrs['Def'] . '</div><div style="padding: 6px; margin: 0; display: none;"><p>';
|
||||
} else {
|
||||
$lang = $parser->attr('lang');
|
||||
$st = '</p><div class="quotebox" style="padding: 0px;"><div onclick="var e,d,c=this.parentNode,a=c.getElementsByTagName(\'div\')[1],b=this.getElementsByTagName(\'span\')[0];if(a.style.display!=\'\'){while(c.parentNode&&(!d||!e||d==e)){e=d;d=(window.getComputedStyle?getComputedStyle(c, null):c.currentStyle)[\'backgroundColor\'];if(d==\'transparent\'||d==\'rgba(0, 0, 0, 0)\')d=e;c=c.parentNode;}a.style.display=\'\';a.style.backgroundColor=d;b.innerHTML=\'▲\';}else{a.style.display=\'none\';b.innerHTML=\'▼\';}" style="font-weight: bold; cursor: pointer; font-size: 0.9em;"><span style="padding: 0 5px;">▼</span>' . $lang['Hidden text'] . '</div><div style="padding: 6px; margin: 0; display: none;"><p>';
|
||||
}
|
||||
|
||||
return $st . $body . '</p></div></div><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'img',
|
||||
'type' => 'img',
|
||||
'parents' => ['inline', 'block', 'url'],
|
||||
'text only' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'body format' => '%^(?:(?:ht|f)tps?://[^\x00-\x1f\s<"]+|data:image/[a-z]+;base64,(?:[a-zA-Z\d/\+\=]+))$%D'
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^(?:(?:ht|f)tps?://[^\x00-\x1f\s<"]+|data:image/[a-z]+;base64,(?:[a-zA-Z\d/\+\=]+))$%D'
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (! isset($attrs['Def'])) {
|
||||
$attrs['Def'] = (substr($body, 0, 11) === 'data:image/') ? 'base64' : basename($body);
|
||||
}
|
||||
|
||||
// тег в подписи
|
||||
if ($parser->attr('isSign')) {
|
||||
if ($parser->attr('showImgSign')) {
|
||||
return '<img src="' . $body . '" alt="' . $attrs['Def'] . '" class="sigimage" />';
|
||||
}
|
||||
} else {
|
||||
// тег в теле сообщения
|
||||
if ($parser->attr('showImg')) {
|
||||
return '<span class="postimg"><img src="' . $body . '" alt="' . $attrs['Def'] . '" /></span>';
|
||||
}
|
||||
}
|
||||
|
||||
$lang = $parser->attr('lang');
|
||||
|
||||
return '<a href="' . $body . '" rel="nofollow"><' . $lang['Image link']. ' - ' . $attrs['Def'] . '></a>';
|
||||
},
|
||||
],
|
||||
['tag' => 'url',
|
||||
'type' => 'url',
|
||||
'parents' => ['inline', 'block'],
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[^\x00-\x1f]+$%',
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^[^\x00-\x1f]+$%D',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (isset($attrs['Def'])) {
|
||||
$url = $attrs['Def'];
|
||||
} else {
|
||||
$url = $body;
|
||||
// возможно внутри была картинка, которая отображается как ссылка
|
||||
if (preg_match('%^<a href=".++(?<=</a>)$%D', $url)) {
|
||||
return $url;
|
||||
}
|
||||
// возможно внутри картинка
|
||||
if (preg_match('%<img src="([^"]+)"%', $url, $match)) {
|
||||
$url = $match[1];
|
||||
}
|
||||
}
|
||||
|
||||
$fUrl = str_replace(array(' ', '\'', '`', '"'), array('%20', '', '', ''), $url);
|
||||
|
||||
if (strpos($url, 'www.') === 0) {
|
||||
$fUrl = 'http://'.$fUrl;
|
||||
} else if (strpos($url, 'ftp.') === 0) {
|
||||
$fUrl = 'ftp://'.$fUrl;
|
||||
} else if (strpos($url, '/') === 0) {
|
||||
$fUrl = $parser->attr('baseUrl') . $fUrl;
|
||||
} else if (!preg_match('%^([a-z0-9]{3,6})://%', $url)) {
|
||||
$fUrl = 'http://'.$fUrl;
|
||||
}
|
||||
|
||||
if ($url === $body) {
|
||||
$url = htmlspecialchars_decode($url, ENT_QUOTES);
|
||||
$url = mb_strlen($url, 'UTF-8') > 55 ? mb_substr($url, 0, 39, 'UTF-8') . ' … ' . mb_substr($url, -10, null, 'UTF-8') : $url;
|
||||
$body = $parser->e($url);
|
||||
}
|
||||
|
||||
return '<a href="' . $fUrl . '" rel="nofollow">' . $body . '</a>';
|
||||
},
|
||||
],
|
||||
['tag' => 'table',
|
||||
'type' => 'table',
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'align' => true,
|
||||
'background' => true,
|
||||
'bgcolor' => true,
|
||||
'border' => true,
|
||||
'bordercolor' => true,
|
||||
'cellpadding' => true,
|
||||
'cellspacing' => true,
|
||||
'frame' => true,
|
||||
'rules' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '</p><table' . $attr . '>' . $body . '</table><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'caption',
|
||||
'type' => 'block',
|
||||
'parents' => ['table'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<caption' . $attr . '><p>' . $body . '</p></caption>';
|
||||
},
|
||||
],
|
||||
['tag' => 'thead',
|
||||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<thead' . $attr . '>' . $body . '</thead>';
|
||||
},
|
||||
],
|
||||
['tag' => 'tbody',
|
||||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<tbody' . $attr . '>' . $body . '</tbody>';
|
||||
},
|
||||
],
|
||||
['tag' => 'tfoot',
|
||||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<tfoot' . $attr . '>' . $body . '</tfoot>';
|
||||
},
|
||||
],
|
||||
['tag' => 'tr',
|
||||
'type' => 'tr',
|
||||
'parents' => ['table', 't'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<tr' . $attr . '>' . $body . '</tr>';
|
||||
},
|
||||
],
|
||||
['tag' => 'th',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'colspan' => true,
|
||||
'rowspan' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<th' . $attr . '><p>' . $body . '</p></th>';
|
||||
},
|
||||
],
|
||||
['tag' => 'td',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'colspan' => true,
|
||||
'rowspan' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<td' . $attr . '><p>' . $body . '</p></td>';
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
$lang = [
|
||||
'Hidden text' => 'Hidden text',
|
||||
'wrote' => 'wrote:', // For [quote]'s
|
||||
'After time' => 'Added later',
|
||||
'After time s' => ' s',
|
||||
'After time i' => ' min',
|
||||
'After time H' => ' h',
|
||||
'After time d' => ' d',
|
||||
'Image link' => 'image', // This is displayed (i.e. <image>) instead of images when "Show images" is disabled in the profile
|
||||
];
|
||||
|
||||
$text = '[table align="center" border="1" bordercolor="#ccc" cellpadding="5" cellspacing="0" style="border-collapse:collapse; width:500px"]
|
||||
[caption][b]Table[/b][/caption]
|
||||
[thead]
|
||||
[tr]
|
||||
[th style=width:50%]Column 1[/th]
|
||||
[th style=width:50%]Column 2[/th]
|
||||
[/tr]
|
||||
[/thead]
|
||||
[tbody]
|
||||
[tr]
|
||||
[td]1.1[/td]
|
||||
[td]
|
||||
[list]
|
||||
[*]1.2
|
||||
[*]1.3
|
||||
[*]1.4
|
||||
[/list]
|
||||
[/td]
|
||||
[/tr]
|
||||
[/tbody]
|
||||
[/table]
|
||||
[size=36]Hello World![/size]
|
||||
[img]data:image/gif;base64,R0lGODlhPAAtANU5AEIyEnV1dbdnQ/7aGjo6Og4ODpOTk7CwsNzc3O7KGu7CCtuwElhYWElJSc7Ozr+/v9rVy6WafeG7E6GhoR0dHWVKDpdLM/HSGmpTErqCAqdXO/7immZmZoSEhNODU9SgCphtBrqOCnJiMnpqOisrK/7+8urq4pSKZOLi2qaACP/lOf7y8qyOENm9EcaqEsqaCpp6DuPHG///AIpiAnpiOv7iIgEBAQAAAOvr6////wAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJFAA5ACwAAAAAPAAtAAAG/8CccEgsGo/IpHLJRNqez6Z02rRZNAIbdcsl2gRgbXc8tWk8WbLyxm67ofC4fE5322/HG27P7/v/gIGCf3hGeoOIiYp9hUWHi5CRjHmSlZGNRHoGAQ44BwEGe6B/m5aJmEN6HDehBDcFOA83DX+upoioQnoTNww4bQ8dNx04DgadOLZ7BgYIewgTzXsHDwicDh0TfNjOe7k5egg3JAc3FMMMN8FtvrYHBWwFDgjwr8Sv8AX1ATjpr/y/KOEgcWMVrwYUYFGggKCBOlvpDhggYCBdgAcLf6lb1UAWAXENEJzzJnDVq4HwCMhyc8AWvD6unEVkgyMAq18U7TwIaGgPr/9ZOEwGEEfhAAcODmw5dPCAokNtJAqI02PzAM5yDQ4wGMrT0R4HbIj9tOowKkNbBvDdOPDznC+aVXHiSHmDAMmeojjl5TOhAYedpTwxYGAVxwQGDbTV5Pep0ygcE7l2zXSrcqBvjyxrnpxqs2fMnjeDDm0Z8502dFKrjnPajZokVgR4EPO6tpEvYYyUgBBhRIUKIyJAKGFbCu40RExEwMBiQYIELlJgiGCiOBMbaDTQzgFBBIwLA8IPuJBAAggREKwrwS5A+xAUGFwMqEG//ngFITCgUO8EDfIVJ7AwXw0A1FfgAOXBcAJxADTInxDYaeAedxhcYOCFNVygwAIVQADywAYZKOCgerFZIEYEAmJIIH0ILgBCgyAqkAEAJD6Bhhg0SDDgivQVWAOCEnz4YYgzkiiDCmZAUUECO9bnJJAAKLDBhyDSaJ0NKsTwxJE2LNmkkywmsMALUW6wgYxWFmdDCy08EUObIixgIZhOarhACCNEiSZ/UFhgohYRpMCkj2AOAIAEH4AQQQ4NpkkiGBNCgIEE4BHKYpQLfNDhg0WwZ6IQAKagQAIXNNrohomesAKnXgjgJ23whSDBqM8loIAEmUq3H6tDxEFEdyAssIAEuGb6wgzo8SqFchWAEMIHH4QAQgXUKTvFbr39Ftxw1nYrRBAAIfkECRQAOQAsAAAAADwALQAABv/AnHBILBqPyKRyyUTans+mdNq0WTQCG3XLJdoEYG13PLVpPFmy8sZuu6HwuHxOd9tvxxtuz+/7/4CBgn94RnqDiImKfYVFh4uQkYx5kpWRjUR6BgEOOAcBBnugf5uWiZhDehw3oQQ3BTgPNw1/rqaIqEJ6EzcMOG0PHTcdOA4GnTi2ewYGCHsIE817Bw8InA4dE3zYznu5OXoINyQHNxTDDDfBbb62BwVsBQ4I8K/Er/AF9QE46a/8vyjhIHFjFa8GFGBRoICggTpb6Q4YIGAgXYAHC3+pW9VAFgFxDRCc8yZw1auB8AjIcnPAFrw+rpxFZIMjAKtfFO08CGhoD6//WThMBhBH4QAHDg5sOXTwgKJDbSQKiNNj8wDOcg0OMBjK09EeB2yI/bTqMCpDWwbw3Tjw85wvmlVx4kh5gwDJnqI45eUzoQGHnaU8MWBgFccEBg201eT3qdMoHBO5ds10q3Kgb48sa56carNnzJ43gw5tGfOdNnRSq45z2o2aJFYEeBDzuraRL2GMlIAQYUSFCiMiQChhWwruNERMRMDAYkGCBC5SYIhgojgTG2g00M4BQQSMCwPCD7iQQAIIERCsK8EuQPsQFBhcDKhBv/54BSEwoFDvBA3yFSewMF8NANRX4ADlwXBCCQA0yN8Q2GngHncYXGDghTVcoMACDWag6EAGADyYQ2wWiBGBgBgSSB+CHG6QgYch8gcFGmLQIMGAKtJXYA0IStCgix/GaJ0NMqhgBhQVJIBjfUz2CMAGTwYpowoxPFGkDUkuyeSKCXCowAYbSKmeDS208EQMZoqwgIVbMqnhAiEAoICYYz5hQYlaRJCCkjtuOQAAEnwAQgQNCikjGBNCgIEE4PW5opwLfFBBeiJCiEaJQgCYggIJXFBooRsKesIKlUIowJ20wReCBJw+l4ACEkQq3X6lChEHEd2BsMACEsQa6QszoFdrE8pVAEIIH3wQAggVUDesFLv19ltwwz1rbRAAIfkECRQAOQAsAAAAADwALQAABv/AnHBILBqPyKRyyUTans+mdNq0WTQCG3XLJdoEYG13PLVpPFmy8sZuu6HwuHxOd9tvxxtuz+/7/4CBgn94RnqDiImKfYVFh4uQkYx5kpWRjUR6BgEOOAcBBnugf5uWiZhDehw3oQQ3BTgPNw1/rqaIqEJ6EzcMOG0PHTcdOA4GnTi2ewYGCHsIE817Bw8InA4dE3zYznu5OXoINyQHNxTDDDfBbb62BwVsBQ4I8K/Er/AF9QE46a/8vyjhIHFjFa8GFGBRoICggTpb6Q4YIGAgXYAHC3+pW9VAFgFxDRCc8yZw1auB8AjIcnPAFrw+rpxFZIMjAKtfFO08CGhoD6//WThMBhBH4QAHDg5sOXTwgKJDbSQKiNNj8wDOcg0OMBjK09EeB2yI/bTqMCpDWwbw3Tjw85wvmlVx4kh5gwDJnqI45eUzoQGHnaU8MWBgFccEBg201eT3qdMoHBO5ds10q3Kgb48sa56carNnzJ43gw5tGfOdNnRSq45z2o2aJFYEeBDzuraRL2GMlIAQYUSFCiMiQChhWwruNERMRMDAYkGCBC5SYIhgojgTG2g00M4BQQSMCwPCD7iQQAIIERCsK8EuQPsQFBhcDKhBv/54BSEwoFDvBA3yFSewMF8NANRX4ADlwXACcQA0yJ8Q2GngHncYXGDghTVcoMACFUAA8sAGGSjgoHqxWSBGBAJiSCB9CC4AQoMgKpABACQ+gYYYNEgw4Ir0FVgDghJ8+GGIM5IogwpmQFFBAjvW5ySQACiwwYcg0midDSrE8MSRNizZpJMsJrDAC1FusIGMVhZnQwstPBFDmyIsYCGYTmq4QAgjRIkmf1BYYKIWEaTApI9gDgCABB+AEEEODaZJIhgTQoCBBOARymKUC3zQ4YNFsGeiEACmoEACFzTa6IaJnrACp14I4Cdt8IUgwajPJaCABJlKtx+rQ8RBRHcgLLCABLhm+sIM6PEqhXIVgBDCBx+EAEIF1Ck7xW69/RbccNZ2K0QQACH5BAkUADkALAAAAAA8AC0AAAb/wJxwSCwaj8ikcslE2p7PpnTatFk0Aht1yyXaBGBtdzy1aTxZsvLGbruh8Lh8Tnfbb8cbbs/v+/+AgYJ/eEZ6g4iJin2FRYeLkJGMeZKVkY1EegYBDjgHAQZ7oH+blomYQ3ocN6EENwU4DzcNf66miKhCehM3DDhtDx03HTgOBp04tnsGBgh7CBPNewcPCJwOHRN82M57uTl6CDckBzcUwww3wW2+tgcFbAUOCPCvxK/wBfUBOOmv/L8o4SBxYxWvBhRgUaCAoIE6W+kOGCBgIF2ABwt/qVvVQBYBcQ0QnPMmcNWrgfAIyHJzwBa8Pq6cRWSDIwCrXxTtPAhoaA+v/1k4TAYQR+EABw4ObDl08ICiQ20kCojTY/MAznINDjAYytPRHgdsiP206jAqQ1sG8N048POcL5pVceJIeYMAyZ6iOOXlM6EBh52lPDFgYBXHBAYNtNXk96nTKBwTuXbNdKtyoG+PLGuenGqzZ8yeN4MObRnznTZ0UquOc9qNmiRWBHgQ87q2kS9hjJSAEGFEhQojIkAoYVsK7jRETETAwGJBggQuUmCIYKI4ExtoNNDOAUEEjAsDwg+4kEACCBEQrCvBLkD7EBQYXAyoQb/+eAUhMKBQ7wQN8hUnsDBfDQDUV+AA5cFwAnFCAOAgf9hp4B53GFxg4IU1XKDAAhWk1/HgBhk8WFxsFogRgYAYEkgfgguAEIGDAICoQIgjPoGGGDRIMKCK9BVYA4IShDBCjDFmMCMAI8qgghlQVJDAjvVFCeQLGMQoI40jqhDDE0ra4CSUUa6YwAJUAqDABhscaZ0NLbTwRAxuirCAhWFGqeECQjqogJprPmFBiVpEkMKTPoY5AAASfOBigyKqh9uEEGAgAXiFrmjmAh90yN9taJQoBIApKJDABTDCuKGiJ6ywaRFf/EkbfCFIIOpzCSggAabS7beqF3AQ0R0ICywgwa2YvjADertOoVwFIITwwQchgFABdclSsVtvvwU3XLXcEhEEADs=[/img]
|
||||
[code]
|
||||
$parser->setBBCodes($bbcodes)
|
||||
->setAttr(\'baseUrl\', \'http://localhost\')
|
||||
->setAttr(\'lang\', $lang)
|
||||
->setAttr(\'showImg\', true)
|
||||
->setAttr(\'showImgSign\', true)
|
||||
->setAttr(\'isSign\', false)
|
||||
->parse($text);
|
||||
[/code]
|
||||
|
||||
[center][background=#00CCCC][url=https://github.com/MioVisman/Parserus]Parserus[/url] BBCode parser[/background][/center]
|
||||
|
||||
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
';
|
||||
|
||||
$parser = new Parserus(ENT_XHTML);
|
||||
$parser->setBBCodes($bbcodes)
|
||||
->setAttr('baseUrl', 'http://localhost')
|
||||
->setAttr('lang', $lang)
|
||||
->setAttr('showImg', true)
|
||||
->setAttr('showImgSign', true)
|
||||
->setAttr('isSign', false)
|
||||
->parse($text);
|
||||
|
||||
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru" dir="ltr">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
</head>
|
||||
<body>' .
|
||||
$parser->getHtml() .
|
||||
'</body>
|
||||
</html>';
|
27
vendor/miovisman/parserus/examples/detectUrls.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->setBBCodes([
|
||||
['tag' => 'url',
|
||||
'type' => 'url',
|
||||
'parents' => ['inline', 'block'],
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[^\x00-\x1f]+$%',
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^[^\x00-\x1f]+$%D',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
#...
|
||||
},
|
||||
],
|
||||
])->parse('Hello www.example.com World!')
|
||||
->detectUrls()
|
||||
->getCode();
|
||||
|
||||
#output: Hello [url]www.example.com[/url] World!
|
63
vendor/miovisman/parserus/examples/detectUrls2.php
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->setBBCodes([
|
||||
['tag' => 'url',
|
||||
'type' => 'url',
|
||||
'parents' => ['inline', 'block'],
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[^\x00-\x1f]+$%',
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^[^\x00-\x1f]+$%D',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
#...
|
||||
},
|
||||
],
|
||||
['tag' => 'h',
|
||||
'type' => 'h',
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
#...
|
||||
},
|
||||
],
|
||||
])->parse('www.example.com/link1[h]Hello www.example.com/link2 World![/h]www.example.com/link3')
|
||||
->detectUrls()
|
||||
->getCode();
|
||||
|
||||
#output: [url]www.example.com/link1[/url][h]Hello www.example.com/link2 World![/h][url]www.example.com/link3[/url]
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
echo $parser->setBlackList(['url'])
|
||||
->setWhiteList()
|
||||
->parse('www.example.com/link1[h]Hello www.example.com/link2 World![/h]www.example.com/link3')
|
||||
->detectUrls()
|
||||
->getCode();
|
||||
|
||||
#output: www.example.com/link1[h]Hello www.example.com/link2 World![/h]www.example.com/link3
|
||||
|
||||
var_dump($parser->getErrors());
|
||||
|
||||
#output: array (size=1)
|
||||
#output: 0 => string 'Тег [url] находится в черном списке' (length=60)
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
echo $parser->setBlackList()
|
||||
->setWhiteList(['h'])
|
||||
->parse('www.example.com/link1[h]Hello www.example.com/link2 World![/h]www.example.com/link3')
|
||||
->detectUrls()
|
||||
->getCode();
|
||||
|
||||
#output: www.example.com/link1[h]Hello www.example.com/link2 World![/h]www.example.com/link3
|
||||
|
||||
var_dump($parser->getErrors());
|
||||
|
||||
#output: array (size=1)
|
||||
#output: 0 => string 'Тег [url] отсутствует в белом списке' (length=62)
|
9
vendor/miovisman/parserus/examples/e.php
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->e("<'abcde'>");
|
||||
|
||||
#output: <'abcde'>
|
126
vendor/miovisman/parserus/examples/getCode.php
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->setBBCodes([
|
||||
['tag' => 'table',
|
||||
'type' => 'table',
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'align' => true,
|
||||
'background' => true,
|
||||
'bgcolor' => true,
|
||||
'border' => true,
|
||||
'bordercolor' => true,
|
||||
'cellpadding' => true,
|
||||
'cellspacing' => true,
|
||||
'frame' => true,
|
||||
'rules' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<table' . $attr . '>' . $body . '</table>';
|
||||
},
|
||||
],
|
||||
['tag' => 'tr',
|
||||
'type' => 'tr',
|
||||
'parents' => ['table', 't'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<tr' . $attr . '>' . $body . '</tr>';
|
||||
},
|
||||
],
|
||||
['tag' => 'th',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'colspan' => true,
|
||||
'rowspan' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<th' . $attr . '>' . $body . '</th>';
|
||||
},
|
||||
],
|
||||
['tag' => 'td',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'colspan' => true,
|
||||
'rowspan' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<td' . $attr . '>' . $body . '</td>';
|
||||
},
|
||||
],
|
||||
])->parse('
|
||||
[table align=right border=1 bordercolor=#ccc cellpadding=5 cellspacing=0 style="border-collapse:collapse; width:500px"]
|
||||
[tr]
|
||||
[th style="width:50%"]Position[/th]
|
||||
[th style=width:50%]Astronaut[/th]
|
||||
[/tr]
|
||||
[tr]
|
||||
[td]Commander[/td]
|
||||
[td]Neil A. Armstrong[/td]
|
||||
[/tr]
|
||||
[tr]
|
||||
[td]Command Module Pilot[/td]
|
||||
[td]Michael Collins[/td]
|
||||
[/tr]
|
||||
[tr]
|
||||
[td]Lunar Module Pilot[/td]
|
||||
[td]Edwin "Buzz" E. Aldrin, Jr.[/td]
|
||||
[/tr]
|
||||
[/table]
|
||||
')->getCode();
|
||||
|
||||
#output:
|
||||
#[table align="right" border="1" bordercolor="#ccc" cellpadding="5" cellspacing="0" style="border-collapse:collapse; width:500px"]
|
||||
# [tr]
|
||||
# [th style=width:50%]Position[/th]
|
||||
# [th style=width:50%]Astronaut[/th]
|
||||
# [/tr]
|
||||
# [tr]
|
||||
# [td]Commander[/td]
|
||||
# [td]Neil A. Armstrong[/td]
|
||||
# [/tr]
|
||||
# [tr]
|
||||
# [td]Command Module Pilot[/td]
|
||||
# [td]Michael Collins[/td]
|
||||
# [/tr]
|
||||
# [tr]
|
||||
# [td]Lunar Module Pilot[/td]
|
||||
# [td]Edwin "Buzz" E. Aldrin, Jr.[/td]
|
||||
# [/tr]
|
||||
#[/table]
|
||||
#
|
41
vendor/miovisman/parserus/examples/getErrors.php
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
$parser->addBBCode([
|
||||
'tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<b>' . $body . '</b>';
|
||||
}
|
||||
])->addBBcode([
|
||||
'tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
]);
|
||||
|
||||
$parser->parse("[i][b] [/b][/i]")->stripEmptyTags(" \n", true);
|
||||
|
||||
$err = [
|
||||
1 => '[%1$s] is in the black list',
|
||||
2 => '[%1$s] is absent in the white list',
|
||||
3 => '[%1$s] can\'t be opened in the [%2$s]',
|
||||
4 => '[/%1$s] was found without a matching [%1$s]',
|
||||
5 => '[/%1$s] is found for single [%1$s]',
|
||||
6 => 'There are no attributes in [%1$s]',
|
||||
7 => 'Primary attribute is forbidden in [%1$s=...]',
|
||||
8 => 'Secondary attributes are forbidden in [%1$s ...]',
|
||||
9 => 'The attribute \'%2$s\' doesn\'t correspond to a template in the [%1$s]',
|
||||
10 => '[%1$s ...] contains unknown secondary attribute \'%2$s\'',
|
||||
11 => 'The body of [%1$s] doesn\'t correspond to a template',
|
||||
12 => '[%1$s] was opened within itself, this is not allowed',
|
||||
13 => 'In the [%1$s] is absent mandatory attribute \'%2$s\'',
|
||||
14 => 'All tags are empty'
|
||||
];
|
||||
|
||||
var_dump($parser->getErrors($err));
|
||||
|
||||
#output: array (size=1)
|
||||
# 0 => string 'All tags are empty' (length=18)
|
34
vendor/miovisman/parserus/examples/smilies.php
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->setSmilies([
|
||||
':)' => 'http://example.com/smilies/smile.png',
|
||||
';)' => 'http://example.com/smilies/wink.png',
|
||||
])->addBBCode([
|
||||
'tag' => 'img',
|
||||
'type' => 'img',
|
||||
'parents' => ['inline', 'block', 'url'],
|
||||
'text only' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'body format' => '%^(?:(?:ht|f)tps?://[^\x00-\x1f\s<"]+|data:image/[a-z]+;base64,(?:[a-zA-Z\d/\+\=]+))$%D'
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^(?:(?:ht|f)tps?://[^\x00-\x1f\s<"]+|data:image/[a-z]+;base64,(?:[a-zA-Z\d/\+\=]+))$%D'
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (! isset($attrs['Def'])) {
|
||||
$attrs['Def'] = (substr($body, 0, 11) === 'data:image/') ? 'base64' : basename($body);
|
||||
}
|
||||
return '<img src="' . $body . '" alt="' . $attrs['Def'] . '">';
|
||||
},
|
||||
])->setSmTpl('<img src="{url}" alt="{alt}">')
|
||||
->parse(":)\n;)")
|
||||
->detectSmilies()
|
||||
->getHTML();
|
||||
|
||||
#output: <img src="http://example.com/smilies/smile.png" alt=":)"><br><img src="http://example.com/smilies/wink.png" alt=";)">
|
61
vendor/miovisman/parserus/examples/stripEmptyTags.php
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
$parser->addBBCode([
|
||||
'tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<b>' . $body . '</b>';
|
||||
}
|
||||
])->addBBcode([
|
||||
'tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
]);
|
||||
|
||||
# №1
|
||||
|
||||
var_dump($parser->parse("[i][b] [/b][/i]")->stripEmptyTags());
|
||||
|
||||
#output: boolean false
|
||||
|
||||
echo $parser->getCode();
|
||||
|
||||
#output: [i][b] [/b][/i]
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
# №2
|
||||
|
||||
var_dump($parser->parse("[i][b] [/b][/i]")->stripEmptyTags(" \n", true));
|
||||
|
||||
#output: boolean true
|
||||
|
||||
echo $parser->getCode();
|
||||
|
||||
#output: [i][b] [/b][/i]
|
||||
|
||||
var_dump($parser->getErrors());
|
||||
|
||||
#output: array (size=1)
|
||||
# 0 => string 'Все теги пустые' (length=28)
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
# №3
|
||||
|
||||
var_dump($parser->parse("[i][b] [/b][/i]")->stripEmptyTags(" \n"));
|
||||
|
||||
#output: boolean true
|
||||
|
||||
echo $parser->getCode();
|
||||
|
||||
#output:
|
||||
|
||||
var_dump($parser->getErrors());
|
||||
|
||||
#output: array (size=1)
|
||||
# empty
|