Browse Source

2017-11-30

Visman 7 năm trước cách đây
mục cha
commit
a4a81c04e0

+ 66 - 0
app/Core/Parser.php

@@ -0,0 +1,66 @@
+<?php
+
+namespace ForkBB\Core;
+
+use Parserus;
+
+class Parser extends Parserus
+{
+    /**
+     * Контейнер
+     * @var Container
+     */
+    protected $c;
+
+    /**
+     * Конструктор
+     *
+     * @param int $flag
+     * @param Container $container
+     */
+    public function __construct($flag, Container $container)
+    {
+        $this->c = $container;
+        parent::__construct($flag);
+        $this->init();
+    }
+
+    /**
+     * Инициализация данных
+     */
+    protected function init()
+    {
+        $bbcodes = include $this->c->DIR_CONFIG . '/defaultBBCode.php';
+        $this->setBBCodes($bbcodes);
+
+        if ($this->c->user->show_smilies == '1'
+            && ($this->c->config->o_smilies_sig == '1' || $this->c->config->o_smilies == '1')
+        ) {
+            $smilies = $this->c->smilies->list; //????
+
+            foreach ($smilies as &$cur) {
+                $cur = $this->c->PUBLIC_URL . '/img/sm/' . $cur;
+            }
+            unset($cur);
+
+            $info = $this->c->BBCODE_INFO;
+
+            $this->setSmilies($smilies)->setSmTpl($info['smTpl'], $info['smTplTag'], $info['smTplBl']);
+        }
+    }
+
+    /**
+     * Метод добавляет один bb-код
+     *
+     * @param array $bb
+     *
+     * @return Parser
+     */
+    public function addBBCode(array $bb)
+    {
+        if ($bb['tag'] == 'quote') {
+            $bb['self nesting'] = (int) $this->c->config->o_quote_depth;
+        }
+        return parent::addBBCode($bb);
+    }
+}

+ 1 - 1
app/Models/ForumList/LoadTree.php

@@ -100,7 +100,7 @@ class LoadTree extends MethodModel
         foreach ($list as $forum) {
             $t = max($max, (int) $forum->mf_mark_all_read);
             if ($forum->last_post > $t) {
-                $time[$id] = $t;
+                $time[$forum->id] = $t;
             }
         }
 

+ 1 - 1
app/Models/Pages/Topic.php

@@ -391,7 +391,6 @@ class Topic extends Page
         $this->topic        = $topic;
         $this->posts        = $posts;
         $this->crumbs       = $this->crumbs($topic);
-        $this->pagination   = $topic->pagination;
         $this->online       = $this->c->Online->calc($this)->info();
         $this->stats        = null;
         $this->form         = $form;
@@ -399,6 +398,7 @@ class Topic extends Page
         if ($topic->showViews) {
             $topic->incViews();
         }
+        $topic->updateVisits();
 /*
         if (! $user->isGuest) {
             $vars = [

+ 22 - 0
app/Models/Post.php

@@ -112,4 +112,26 @@ class Post extends DataModel
         }
         return $controls;
     }
+
+    /**
+     * HTML код сообщения
+     * 
+     * @return string
+     */
+    public function html()
+    {
+        $bbWList = $this->c->config->p_message_bbcode == '1' ? null : [];
+        $bbBList = $this->c->config->p_message_img_tag == '1' ? [] : ['img'];
+
+        $parser = $this->c->Parser->setAttr('isSign', false)
+            ->setWhiteList($bbWList)
+            ->setBlackList($bbBList)
+            ->parse($this->cens()->message);
+
+        if ($this->hide_smilies != '1' && $this->c->config->o_smilies == '1') {
+            $parser->detectSmilies();
+        }
+
+        return $parser->getHtml();
+    }
 }

+ 45 - 0
app/Models/Topic.php

@@ -330,6 +330,7 @@ class Topic extends DataModel
             $cur = $this->c->ModelPost->setAttrs($cur);
         }
         unset($cur);
+        $this->timeMax = $timeMax;
         return $posts;
     }
 
@@ -355,4 +356,48 @@ class Topic extends DataModel
 
         $this->c->DB->query($sql, $vars);
     }
+
+    /**
+     * Обновление меток последнего визита и последнего прочитанного сообщения
+     */
+    public function updateVisits()
+    {
+        if ($this->c->user->isGuest) {
+            return;
+        }
+
+        $vars = [
+            ':uid'   => $this->c->user->id,
+            ':tid'   => $this->id,
+            ':read'  => $this->mt_last_read,
+            ':visit' => $this->mt_last_visit,
+        ];
+        $flag = false;
+
+        if (false !== $this->hasNew) {
+            $flag = true;
+            $vars[':visit'] = $this->last_post;
+        }
+        if (false !== $this->hasUnread && $this->timeMax > $this->hasUnread) {
+            $flag = true;
+            $vars[':read'] = $this->timeMax;
+        }
+
+        if ($flag) {
+            if (empty($this->mt_last_read) && empty($this->mt_last_visit)) {
+                $sql = 'INSERT INTO ::mark_of_topic (uid, tid, mt_last_visit, mt_last_read)
+                        SELECT ?i:uid, ?i:tid, ?i:visit, ?i:read
+                        FROM ::groups
+                        WHERE NOT EXISTS (SELECT 1
+                                          FROM ::mark_of_topic
+                                          WHERE uid=?i:uid AND tid=?i:tid)
+                        LIMIT 1';
+            } else {
+                $sql = 'UPDATE ::mark_of_topic
+                        SET mt_last_visit=?i:visit, mt_last_read=?i:read
+                        WHERE uid=?i:uid AND tid=?i:tid';
+            }
+            $this->c->DB->exec($sql, $vars);
+        }
+    }
 }

+ 22 - 0
app/Models/User.php

@@ -186,4 +186,26 @@ class User extends DataModel
     {
         return isset($this->c->Online->online[$this->id]);
     }
+
+    /**
+     * HTML код подписи
+     * 
+     * @return string
+     */
+    protected function gethtmlSign()
+    {
+        $bbWList = $this->c->config->p_sig_bbcode == '1' ? $this->c->BBCODE_INFO['forSign'] : [];
+        $bbBList = $this->c->config->p_sig_img_tag == '1' ? [] : ['img'];
+
+        $parser = $this->c->Parser->setAttr('isSign', true)
+            ->setWhiteList($bbWList)
+            ->setBlackList($bbBList)
+            ->parse($this->cens()->signature);
+
+        if ($this->c->config->o_smilies_sig == '1') {
+            $parser->detectSmilies();
+        }
+
+        return $parser->getHtml();
+    }
 }

+ 20 - 24
app/config/defaultBBCode.php

@@ -4,10 +4,8 @@ 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('%(</?p>)(?:\s*?<br>){1,2}%', '$1', '<p>' . $body . '</p>');
          $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
@@ -32,9 +30,7 @@ return [
          '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>';
+         return '</p><div class="codebox"><pre><code>' . trim($body, "\n\r") . '</code></pre></div><p>';
      },
     ],
     ['tag' => 'b',
@@ -86,7 +82,7 @@ return [
      },
     ],
     ['tag' => 'color',
-     'self nesting' => true,
+     'self nesting' => 5,
      '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))$%',
@@ -97,7 +93,7 @@ return [
      },
     ],
     ['tag' => 'colour',
-     'self nesting' => true,
+     'self nesting' => 5,
      '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))$%',
@@ -108,7 +104,7 @@ return [
      },
     ],
     ['tag' => 'background',
-     'self nesting' => true,
+     'self nesting' => 5,
      '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))$%',
@@ -119,7 +115,7 @@ return [
      },
     ],
     ['tag' => 'size',
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'Def' => [
              'format' => '%^[1-9]\d*(?:em|ex|pt|px|\%)?$%',
@@ -156,7 +152,7 @@ return [
      },
     ],
     ['tag' => 'font',
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'Def' => [
              'format' => '%^[a-z\d, -]+$%i',
@@ -187,7 +183,7 @@ return [
     ],
     ['tag' => '*',
      'type' => 'block',
-     'self nesting' => true,
+     'self nesting' => 5,
      'parents' => ['list'],
      'auto' => true,
      'handler' => function($body) {
@@ -196,7 +192,7 @@ return [
     ],
     ['tag' => 'list',
      'type' => 'list',
-     'self nesting' => true,
+     'self nesting' => 5,
      'tags only' => true,
      'attrs' => [
          'Def' => true,
@@ -251,7 +247,7 @@ return [
     ],
     ['tag' => 'quote',
      'type' => 'block',
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'Def' => true,
          'no attr' => true,
@@ -268,7 +264,7 @@ return [
     ],
     ['tag' => 'spoiler',
      'type' => 'block',
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'Def' => true,
          'no attr' => true,
@@ -354,7 +350,7 @@ return [
          }
 
          if ($url === $body) {
-             $url = htmlspecialchars_decode($url, ENT_QUOTES);
+             $url = htmlspecialchars_decode($url, ENT_QUOTES | ENT_HTML5);
              $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);
          }
@@ -365,7 +361,7 @@ return [
     ['tag' => 'table',
      'type' => 'table',
      'tags only' => true,
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'no attr' => true,
          'style' => true,
@@ -390,7 +386,7 @@ return [
     ['tag' => 'caption',
      'type' => 'block',
      'parents' => ['table'],
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'no attr' => true,
          'style' => true,
@@ -407,7 +403,7 @@ return [
      'type' => 't',
      'parents' => ['table'],
      'tags only' => true,
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'no attr' => true,
          'style' => true,
@@ -424,7 +420,7 @@ return [
      'type' => 't',
      'parents' => ['table'],
      'tags only' => true,
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'no attr' => true,
          'style' => true,
@@ -441,7 +437,7 @@ return [
      'type' => 't',
      'parents' => ['table'],
      'tags only' => true,
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'no attr' => true,
          'style' => true,
@@ -458,7 +454,7 @@ return [
      'type' => 'tr',
      'parents' => ['table', 't'],
      'tags only' => true,
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'no attr' => true,
          'style' => true,
@@ -474,7 +470,7 @@ return [
     ['tag' => 'th',
      'type' => 'block',
      'parents' => ['tr'],
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'no attr' => true,
          'style' => true,
@@ -492,7 +488,7 @@ return [
     ['tag' => 'td',
      'type' => 'block',
      'parents' => ['tr'],
-     'self nesting' => true,
+     'self nesting' => 5,
      'attrs' => [
          'no attr' => true,
          'style' => true,

+ 6 - 6
app/templates/topic.tpl

@@ -22,7 +22,7 @@
 @endsection
 @section('pagination')
         <nav class="f-pages">
-@foreach($p->pagination as $cur)
+@foreach($p->topic->pagination as $cur)
 @if($cur[2])
           <span class="f-page active">{{ $cur[1] }}</span>
 @elseif($cur[1] === 'space')
@@ -40,7 +40,7 @@
 @extends('layouts/main')
     <div class="f-nav-links">
 @yield('crumbs')
-@if($p->topic->canReply || $p->topic->closed || $p->pagination)
+@if($p->topic->canReply || $p->topic->closed || $p->topic->pagination)
       <div class="f-links-b clearfix">
 @yield('pagination')
 @yield('linkpost')
@@ -70,7 +70,7 @@
 @else
               <li class="f-username">{{ $post->user->username }}</li>
 @endif
-@if($post->showUserAvatar)
+@if($post->showUserAvatar && $post->user->avatar)
               <li class="f-avatar">
                 <img alt="{{ $post->user->username }}" src="{!! $post->user->avatar !!}">
               </li>
@@ -91,12 +91,12 @@
 @endif
           </address>
           <div class="f-post-right f-post-main">
-            {!! $post->message !!}
+            {!! $post->html() !!}
           </div>
 @if($post->showSignature && $post->user->signature)
           <div class="f-post-right f-post-signature">
             <hr>
-            {!! $post->user->signature !!}
+            {!! $post->user->htmlSign !!}
           </div>
 @endif
         </div>
@@ -118,7 +118,7 @@
 @endforeach
     </section>
     <div class="f-nav-links">
-@if($p->topic->canReply || $p->topic->closed || $p->pagination)
+@if($p->topic->canReply || $p->topic->closed || $p->topic->pagination)
       <div class="f-links-a clearfix">
 @yield('linkpost')
 @yield('pagination')

+ 9 - 8
composer.lock

@@ -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": "f222f403c8d48f00cb5e3e37f680ebcb",
-    "content-hash": "b8c1ffae094a89502ad8a3c60385d4b8",
+    "hash": "683b977706502db4bb7fc7ba3cd8ca71",
+    "content-hash": "2299621b481bdbc8ce629eee53b1b82e",
     "packages": [
         {
             "name": "artoodetoo/dirk",
@@ -55,16 +55,16 @@
         },
         {
             "name": "miovisman/parserus",
-            "version": "0.9.1",
+            "version": "dev-master",
             "source": {
                 "type": "git",
                 "url": "https://github.com/MioVisman/Parserus.git",
-                "reference": "d039178d46c989ebb8eb89970b52eb6ce927c817"
+                "reference": "bbdade91cfc4927ebb8b5b984f90a52075f75ece"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/MioVisman/Parserus/zipball/d039178d46c989ebb8eb89970b52eb6ce927c817",
-                "reference": "d039178d46c989ebb8eb89970b52eb6ce927c817",
+                "url": "https://api.github.com/repos/MioVisman/Parserus/zipball/bbdade91cfc4927ebb8b5b984f90a52075f75ece",
+                "reference": "bbdade91cfc4927ebb8b5b984f90a52075f75ece",
                 "shasum": ""
             },
             "require": {
@@ -93,14 +93,15 @@
                 "bbcode",
                 "parser"
             ],
-            "time": "2016-11-26 06:56:51"
+            "time": "2017-11-21 06:34:31"
         }
     ],
     "packages-dev": [],
     "aliases": [],
     "minimum-stability": "stable",
     "stability-flags": {
-        "artoodetoo/dirk": 20
+        "artoodetoo/dirk": 20,
+        "miovisman/parserus": 20
     },
     "prefer-stable": false,
     "prefer-lowest": false,

+ 6 - 6
vendor/composer/installed.json

@@ -49,23 +49,23 @@
     },
     {
         "name": "miovisman/parserus",
-        "version": "0.9.1",
-        "version_normalized": "0.9.1.0",
+        "version": "dev-master",
+        "version_normalized": "9999999-dev",
         "source": {
             "type": "git",
             "url": "https://github.com/MioVisman/Parserus.git",
-            "reference": "d039178d46c989ebb8eb89970b52eb6ce927c817"
+            "reference": "bbdade91cfc4927ebb8b5b984f90a52075f75ece"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/MioVisman/Parserus/zipball/d039178d46c989ebb8eb89970b52eb6ce927c817",
-            "reference": "d039178d46c989ebb8eb89970b52eb6ce927c817",
+            "url": "https://api.github.com/repos/MioVisman/Parserus/zipball/bbdade91cfc4927ebb8b5b984f90a52075f75ece",
+            "reference": "bbdade91cfc4927ebb8b5b984f90a52075f75ece",
             "shasum": ""
         },
         "require": {
             "php": ">=5.4.0"
         },
-        "time": "2016-11-26 06:56:51",
+        "time": "2017-11-21 06:34:31",
         "type": "library",
         "installation-source": "dist",
         "autoload": {

+ 1 - 1
vendor/miovisman/parserus/LICENSE

@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2016 Visman
+Copyright (c) 2016-2017 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

+ 111 - 45
vendor/miovisman/parserus/Parserus.php

@@ -1,7 +1,7 @@
 <?php
 
 /**
- * @copyright  Copyright (c) 2016 Visman. All rights reserved.
+ * @copyright  Copyright (c) 2016-2017 Visman. All rights reserved.
  * @author     Visman <mio.visman@yandex.ru>
  * @link       https://github.com/MioVisman/Parserus
  * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
@@ -119,6 +119,12 @@ class Parserus
      */
     protected $strict = false;
 
+    /**
+     * Максимальная глубина дерева тегов при строгом режиме поиска ошибок
+     * @var int
+     */
+    protected $maxDepth;
+
     /**
      * Конструктор
      *
@@ -131,14 +137,15 @@ class Parserus
         }
         $this->eFlags = $flag | ENT_QUOTES | ENT_SUBSTITUTE;
         $this->tRepl = in_array($flag, [ENT_HTML5, ENT_HTML401])
-                     ? ['<br>',   '&nbsp; &nbsp; ', '&nbsp; ', ' &nbsp;']
-                     : ['<br />', '&#160; &#160; ', '&#160; ', ' &#160;'];
+            ? ['<br>',   '&nbsp; &nbsp; ', '&nbsp; ', ' &nbsp;']
+            : ['<br />', '&#160; &#160; ', '&#160; ', ' &#160;'];
     }
 
     /**
      * Метод добавляет один bb-код
      *
      * @param  array    $bb   Массив описания bb-кода
+     *
      * @return Parserus $this
      */
     public function addBBCode(array $bb)
@@ -174,7 +181,7 @@ class Parserus
         }
 
         if (isset($bb['self nesting'])) {
-            $res['self nesting'] = (bool) $bb['self nesting'];
+            $res['self nesting'] = (int) $bb['self nesting'] > 0 ? (int) $bb['self nesting'] : false;
         }
 
         if (isset($bb['recursive'])) {
@@ -248,6 +255,7 @@ class Parserus
      * Метод задает массив bb-кодов
      *
      * @param  array    $bbcodes Массив описаний bb-кодов
+     *
      * @return Parserus $this
      */
     public function setBBCodes(array $bbcodes)
@@ -276,6 +284,7 @@ class Parserus
      * Метод задает массив смайлов
      *
      * @param  array    $smilies Ассоциативный массив смайлов
+     *
      * @return Parserus $this
      */
     public function setSmilies(array $smilies)
@@ -331,6 +340,7 @@ class Parserus
      * @param  string   $tpl  Строка шаблона, например: <img src="{url}" alt="{alt}">
      * @param  string   $tag  Имя тега под которым идет отображение смайлов
      * @param  array    $bl   Список тегов в которых не нужно отображать смайлы
+     *
      * @return Parserus $this
      */
     public function setSmTpl($tpl, $tag = 'img', array $bl = ['url'])
@@ -356,6 +366,7 @@ class Parserus
      * Метод устанавливает список разрешенных bb-кодов
      *
      * @param  mixed    $list Массив bb-кодов, null и т.д.
+     *
      * @return Parserus $this
      */
     public function setWhiteList($list = null)
@@ -368,6 +379,7 @@ class Parserus
      * Метод устанавливает список запрещенных bb-кодов
      *
      * @param  mixed    $list Массив bb-кодов, null и т.д.
+     *
      * @return Parserus $this
      */
     public function setBlackList($list = null)
@@ -381,6 +393,7 @@ class Parserus
      *
      * @param  string   $name Имя переменной
      * @param  mixed    $val  Значение переменной
+     *
      * @return Parserus $this
      */
     public function setAttr($name, $val)
@@ -392,8 +405,9 @@ class Parserus
     /**
      * Метод для получения значения переменной
      *
-     * @param  string     $name Имя переменной
-     * @return mixed|null       Значение переменной или null, если переменная не была задана ранее
+     * @param  string $name Имя переменной
+     *
+     * @return mixed  Значение переменной или null, если переменная не была задана ранее
      */
     public function attr($name)
     {
@@ -407,15 +421,16 @@ class Parserus
      * @param  int    $parentId Указатель на родителя
      * @param  array  $attrs    Массив атрибутов тега
      * @param  bool   $textOnly Флаг. Если true, то в теле только текст
+     *
      * @return int              Указатель на данный тег
      */
-    protected function addTagNode($tag, $parentId = null, $attrs = [], $textOnly = false)
+    protected function addTagNode($tag, $parentId = null, array $attrs = [], $textOnly = false)
     {
         $this->data[++$this->dataId] = [
-            'tag' => $tag,
-            'parent' => $parentId,
+            'tag'      => $tag,
+            'parent'   => $parentId,
             'children' => [],
-            'attrs' => $attrs,
+            'attrs'    => $attrs,
         ];
 
         if ($textOnly) {
@@ -434,14 +449,14 @@ class Parserus
      *
      * @param  string $text     Текст
      * @param  int    $parentId Указатель на родителя
+     *
      * @return string           Пустая строка
      */
     protected function addTextNode($text, $parentId)
     {
         if (isset($text[0])) {
-
             $this->data[++$this->dataId] = [
-                'text' => $text,
+                'text'   => $text,
                 'parent' => $parentId,
             ];
 
@@ -455,6 +470,7 @@ class Parserus
      * Метод нормализует содержимое атрибута
      *
      * @param  string $attr Содержимое атрибута полученное из регулярного выражения
+     *
      * @return string
      */
     protected function getNormAttr($attr)
@@ -476,6 +492,7 @@ class Parserus
      * @param  string           $tag  Имя обрабатываемого тега
      * @param  string           $type "Тип атрибутов" = ' ', '=' или ']'
      * @param  string           $text Текст из которого выделяются атрибуты
+     *
      * @return null|array
      */
     protected function parseAttrs($tag, $type, $text)
@@ -575,8 +592,8 @@ class Parserus
 
         return [
             'attrs' => $attrs,
-            'tag' => $tagText,
-            'text' => $text,
+            'tag'   => $tagText,
+            'text'  => $text,
         ];
     }
 
@@ -584,6 +601,7 @@ class Parserus
      * Метод определяет указатель на родительский тег для текущего
      *
      * @param  string    $tag Имя тега
+     *
      * @return int|false      false, если невозможно подобрать родителя
      */
     protected function findParent($tag)
@@ -629,9 +647,10 @@ class Parserus
      * @param  string      $tag   Имя тега
      * @param  array       $attrs Массив атрибутов
      * @param  string      $text  Текст из которого выделяется тело тега
+     *
      * @return array|false        false в случае ошибки
      */
-    protected function validationTag($tag, $attrs, $text)
+    protected function validationTag($tag, array $attrs, $text)
     {
         if (empty($attrs)) {
             $attrs['no attr'] = null;
@@ -691,8 +710,8 @@ class Parserus
 
         return [
             'attrs' => $attrs,
-            'body' => $flag ? $body : null,
-            'end' => $end,
+            'body'  => $flag ? $body : null,
+            'end'   => $end,
         ];
     }
 
@@ -702,6 +721,7 @@ class Parserus
      * @param  string $tag     Имя обрабатываемого тега
      * @param  string $curText Текст до тега, который еще не был учтен
      * @param  string $tagText Текст самого тега - [/tag]
+     *
      * @return string          Пустая строка, если тег удалось закрыть
      */
     protected function closeTag($tag, $curText, $tagText) {
@@ -715,7 +735,9 @@ class Parserus
         $curTag = $this->data[$curId]['tag'];
 
         while ($curTag !== $tag && $curId > 0) {
-            if (false === $this->bbcodes[$curTag]['auto']) {
+            if ($this->bbcodes[$tag]['type'] === 'inline'
+                || false === $this->bbcodes[$curTag]['auto']
+            ) {
                 break;
             }
 
@@ -753,6 +775,7 @@ class Parserus
         $this->smOn = false;
         $this->errors = [];
         $this->strict = isset($opts['strict']) ? (bool) $opts['strict'] : false;
+        $this->maxDepth = isset($opts['depth']) ? (int) $opts['depth'] : 10;
     }
 
     /**
@@ -760,9 +783,10 @@ class Parserus
      *
      * @param  string   $text Обрабатываемый текст
      * @param  array    $opts Ассоциативный массив опций
+     *
      * @return Parserus $this
      */
-    public function parse($text, $opts = [])
+    public function parse($text, array $opts = [])
     {
         $this->reset($opts);
         $curText = '';
@@ -774,13 +798,13 @@ class Parserus
         while (($match = preg_split('%(\[(/)?(' . ($recCount ? $recTag : '[a-z\*][a-z\d-]{0,10}') . ')((?(1)\]|[=\]\x20])))%i', $text, 2, PREG_SPLIT_DELIM_CAPTURE))
                && isset($match[1])
         ) {
-         /* $match[0] - текст до тега
-          * $match[1] - [ + (|/) + имя тега + (]| |=)
-          * $match[2] - (|/)
-          * $match[3] - имя тега
-          * $match[4] - тип атрибутов --> (]| |=)
-          * $match[5] - остаток текста до конца
-          */
+            /* $match[0] - текст до тега
+             * $match[1] - [ + (|/) + имя тега + (]| |=)
+             * $match[2] - (|/)
+             * $match[3] - имя тега
+             * $match[4] - тип атрибутов --> (]| |=)
+             * $match[5] - остаток текста до конца
+             */
             $tagText = $match[1];
             $curText .= $match[0];
             $text = $match[5];
@@ -869,13 +893,62 @@ class Parserus
         }
 
         $this->addTextNode($curText . $text, $this->curId);
+
+        if ($this->strict) {
+            $this->searchError();
+        }
+
         return $this;
     }
 
+    /**
+     * Метод проверяет глубину дерева тегов
+     * Метод проверяет лимит вложенности тегов в самих себя
+     *
+     * @param int   $id    Указатель на текущий тег
+     * @param int   $depth Глубина дерева на текущий момент
+     * @param array $tags  Массив количества вложений тегов с включенным 'self nesting'
+     *
+     * @return bool
+     */
+    protected function searchError($id = 0, $depth = -1, array $tags = [])
+    {
+        if (isset($this->data[$id]['text'])) {
+            return false;
+        }
+
+        ++$depth;
+
+        if ($depth > $this->maxDepth) {
+            $this->errors[] = [15, $this->maxDepth];
+            return true;
+        }
+
+        $tag = $this->data[$id]['tag'];
+        if (false !== $this->bbcodes[$tag]['self nesting']) {
+            if (isset($tags[$tag])) {
+                ++$tags[$tag];
+            } else {
+                $tags[$tag] = 0;
+            }
+            if ($tags[$tag] > $this->bbcodes[$tag]['self nesting']) {
+                $this->errors[] = [16, $tag, $this->bbcodes[$tag]['self nesting']];
+                return true;
+            }
+        }
+        foreach ($this->data[$id]['children'] as $child) {
+            if ($this->searchError($child, $depth, $tags)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Метод возвращает HTML построенный на основании дерева тегов
      *
      * @param  int    $id Указатель на текущий тег
+     *
      * @return string
      */
     public function getHtml($id = 0)
@@ -952,6 +1025,7 @@ class Parserus
      * Метод возвращает текст с bb-кодами построенный на основании дерева тегов
      *
      * @param  int    $id Указатель на текущий тег
+     *
      * @return string
      */
     public function getCode($id = 0)
@@ -1021,6 +1095,7 @@ class Parserus
      * @param  string   $tag      Имя для создания bb-кода
      * @param  string   $pattern  Регулярное выражение для поиска
      * @param  bool     $textOnly Флаг. true, если содержимое созданного тега текстовое
+     *
      * @return Parserus $this
      */
     protected function detect($tag, $pattern, $textOnly)
@@ -1073,7 +1148,7 @@ class Parserus
                 $pos = $match[1] + strlen($match[0]);
             }
 
-            $this->addTextNode($this->endStr($this->data[$id]['text'], $pos), $pid);
+            $this->addTextNode((string) substr($this->data[$id]['text'], $pos), $pid);
             unset($this->data[$id]);
 
             $this->data[$pid]['children'] = array_merge($this->data[$pid]['children'], $arrEnd);
@@ -1112,6 +1187,7 @@ class Parserus
      *
      * @param  string $mask Маска символов, которые не учитываются при определении пустоты текстовых узлов
      * @param  int    $id   Указатель на текущий тег
+     *
      * @return bool         Если true, то тег/узел пустой
      */
     protected function stripEmptyTags_($mask, $id)
@@ -1155,10 +1231,12 @@ class Parserus
     /**
      * Метод возвращает массив ошибок
      *
-     * @param  array $lang Массив строк шаблонов описания ошибок
+     * @param  array $lang   Массив строк шаблонов описания ошибок
+     * @param  array $errors Массив, который дополняется ошибками
+     *
      * @return array
      */
-    public function getErrors(array $lang = [])
+    public function getErrors(array $lang = [], array $errors = [])
     {
         $defLang = [
             1 => 'Тег [%1$s] находится в черном списке',
@@ -1174,11 +1252,11 @@ class Parserus
             11 => 'Тело тега [%1$s] не соответствует шаблону',
             12 => 'Тег [%1$s] нельзя открыть внутри аналогичного тега',
             13 => 'В теге [%1$s] отсутствует обязательный атрибут \'%2$s\'',
-            14 => 'Все теги пустые'
+            14 => 'Все теги пустые',
+            15 => 'Глубина дерева тегов больше %1$s',
+            16 => 'Тег [%1$s] вложен в себя больше %2$s раз',
         ];
 
-        $errors = [];
-
         foreach ($this->errors as $args) {
             $err = array_shift($args);
 
@@ -1200,23 +1278,11 @@ class Parserus
      * Метод преобразует специальные символы в HTML-сущности
      *
      * @param  string $text
+     *
      * @return string
      */
     public function e($text)
     {
         return htmlspecialchars($text, $this->eFlags, 'UTF-8');
     }
-
-    /**
-     * Метод возвращает окончание строки
-     *
-     * @param  string $str Текст
-     * @param  int    $pos Начальная позиция в байтах с которой идет возврат текста
-     * @return string
-     */
-    protected function endStr($str, $pos)
-    {
-        $s = substr($str, $pos);
-        return false === $s  ? '' : $s;
-    }
 }

+ 0 - 20
vendor/miovisman/parserus/examples/_first.php

@@ -1,20 +0,0 @@
-<?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>

+ 0 - 20
vendor/miovisman/parserus/examples/_second.php

@@ -1,20 +0,0 @@
-<?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>

+ 0 - 20
vendor/miovisman/parserus/examples/_third.php

@@ -1,20 +0,0 @@
-<?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>

+ 0 - 50
vendor/miovisman/parserus/examples/attr.php

@@ -1,50 +0,0 @@
-<?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>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 554
vendor/miovisman/parserus/examples/bbcodes_test.php


+ 0 - 27
vendor/miovisman/parserus/examples/detectUrls.php

@@ -1,27 +0,0 @@
-<?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!

+ 0 - 63
vendor/miovisman/parserus/examples/detectUrls2.php

@@ -1,63 +0,0 @@
-<?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)

+ 0 - 9
vendor/miovisman/parserus/examples/e.php

@@ -1,9 +0,0 @@
-<?php
-
-include '../Parserus.php';
-
-$parser = new Parserus();
-
-echo $parser->e("<'abcde'>");
-
-#output: &lt;&apos;abcde&apos;&gt;

+ 0 - 126
vendor/miovisman/parserus/examples/getCode.php

@@ -1,126 +0,0 @@
-<?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]
-#

+ 0 - 41
vendor/miovisman/parserus/examples/getErrors.php

@@ -1,41 +0,0 @@
-<?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)

+ 0 - 34
vendor/miovisman/parserus/examples/smilies.php

@@ -1,34 +0,0 @@
-<?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=";)">

+ 0 - 61
vendor/miovisman/parserus/examples/stripEmptyTags.php

@@ -1,61 +0,0 @@
-<?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

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác