X   Сообщение сайта
(Сообщение закроется через 3 секунды)



 

Здравствуйте, гость (

| Вход | Регистрация )

Открыть тему
Тема закрыта
> Не работает Скрытый текст ip board
prolisk
prolisk
Topic Starter сообщение 4.10.2016, 20:50; Ответить: prolisk
Сообщение #1


На форуме ip board 3.4.6 не так как нужно работает bbcode hide - хук [WR] Скрытый текст v1.2.0.
Вывод тега обычный:
[hide='20']скрытый текст для пользователей, которые написали больше 20 сообщений[/hide]

Вот должно работать по идеи, но если в кавычках - то работает не с кол-вом сообщений, а с именем пользователя.
Вывод ошибку: "ВЫ должны быть пользователем с именем 20".

Если кавычки убрать - работает как нужно.
То есть проблема:
1) или в кавычках, которые подставляются сами. (по кавычкам разбор далее)
2) или в самом хуке, который не переводит числа в кавычках с переменной "имя_пользователя" в переменную "кол-во сообщений".

может в коде где ошибка? или что удалить для того, чтобы осталось только hide для незарегистрированных и по кол-ву сообщений? (вырезаем привязку к ИД пользователя, к имени, к репутации - переменные $cond, если не ошибаюсь).

Разбор по кавычкам:
На одном хука (hide) для ip board 3.4.* подставляются кавычки в тег.
За создание самого тега отвечает файл class_private_data. Методом несколько дневных тестов определился с основными составляющими документа и кто за что отвечает.
Вот код всего дока:
[spoiler="код всего"]
<?php

class classPrivateData
{
    protected $registry;
    protected $DB;
    protected $settings;
    protected $lang;
    protected $member;
    protected $cache;
    
    protected $css_added        = false;
    
    public    $priv_data        = array();
    protected $tag                = 'hide';
    
    protected $post              = array();
    
    protected $cond_types         = array('reg'     => 'reg',
                                        'g'        => 'group',
                                        'p'        => 'posts',
                                        'rep'    => 'rep',
                                        'r'        => 'rep',
                                        );
    
    /**
     * Constructor
     *
     * @return     void
     */
    public function __construct( ipsRegistry $registry )
    {
        #Seup shortcuts
        $this->registry = $registry;
        $this->DB       = $this->registry->DB();
        $this->settings =& $this->registry->fetchSettings();
        $this->request  =& $this->registry->fetchRequest();
        $this->lang     = $this->registry->getClass('class_localization');
        $this->member   = $this->registry->member();
        $this->memberData =& $this->registry->member()->fetchMemberData();
        $this->cache    = $this->registry->cache();
        $this->caches   =& $this->registry->cache()->fetchCaches();
        
        #Get language
        $this->registry->getClass('class_localization')->loadLanguageFile( array( 'public_private_data' ), 'core' );
    }
    
    /**
     * Проверить условия и добавить скрытый текст в тело сообщения
     *
     * @param array $row - как минимум, необходимы: 'post', 'private_data', 'author_id'.
     * @return string
     */
    public function showPrivateData($row)
    {
        $passed = 0;
        $hash     = $this->_thrawData($row['private_data']);
        
        if(!is_array($hash) or !count($hash))
        {
            return $row['post'];
        }
        
        $this->post = $row;
        
        //-----------------------------------------
        // Последовательно обрабатываем каждый "скрытый текст"
        //-----------------------------------------
        
        foreach($hash as $id => $data)
        {
            //-----------------------------------------
            // Опции, умолчания, параметры
            //-----------------------------------------
        
            $data['options'] = $data['options'] ? str_split($data['options']) : array();
            
            #Свернут или развернут текст по умолчанию?
            $data['state'] = in_array('c', $data['options']) ? 'collapsed' : $this->settings['priv_default_state'];
            
            //-----------------------------------------
            // Базовые условия
            //-----------------------------------------
            
            #Супермодераторы видят весь скрытый текст
            if( $this->memberData['g_is_supmod'] )
            {
                $passed = 1;
            }
            #Смотрим свой собственный скрытый текст
            elseif( $this->memberData['member_id'] and ( $this->memberData['member_id'] == $row['author_id']) )
            {
                $passed = 1;
            }
            
            //-----------------------------------------
            // Указанные пользователем условия
            //-----------------------------------------
            
            else
            {
                $ret_conds            = array();
                
                #Получаем блоки условий
                $blocks = explode(',', $data['conditions']);
                
                #Последовательно проверяем все блоки
                foreach($blocks as $b_id => $block)
                {
                    $block_passed = 1;
                    
                    foreach(explode('+', $block) as $cond)
                    {
                        $ret = $this->pdCheckCondition($cond);
                        
                        if( ! $ret['passed'] )
                        {
                            $block_passed = 0;
                        }
                        
                        $ret_conds[$b_id][] = $ret;
                    }
                    
                    #Блок условий успешно выполнен
                    if( $block_passed )
                    {
                        $passed = 1;
                    }
                }
                
                //(print_r($ret_conds));
            }
        
            //-----------------------------------------
            // Результат: УСПЕХ
            //-----------------------------------------
            
            if( $passed )
            {
                $row['post'] = str_replace('<!--pd_'.$id.'-->', $this->registry->getClass('output')->getTemplate('private_data')->private_data_opened( $data ), $row['post']);
                
                if( ! $this->css_added )
                {
                    ipsRegistry::getClass('output')->addToDocumentHead( 'importcss', ipsRegistry::$settings['public_dir'] . 'style_css/' . ipsRegistry::getClass('output')->skin['_csscacheid'] . '/private_data.css' );
                    $this->css_added = true;
                }
            }
            
            //-----------------------------------------
            // Результат: ПРОВАЛ
            //-----------------------------------------
            
            else
            {
                switch($this->settings['priv_hide_mode'])
                {
                    case 1:
                        $replacer = '';
                        break;
                    case 2:
                    default:
                        $replacer = $this->registry->getClass('output')->getTemplate('private_data')->private_data_closed( $data, $ret_conds );
                        break;
                }
                
                $row['post'] = str_replace('<!--pd_'.$id.'-->', $replacer, $row['post']);
            }
        }
        
        return $row['post'];
    }
    
    /**
     * Проверить, имеем ли мы доступ к аттачу
     *
     * @param    array    $row    - необходим 'attach_pd_conditions'
     * @return     integer
     */
    public function checkAttachment($row)
    {
        #Аттач не был скрыт - сразу выходим
        if( ! $row['attach_pd_conditions'] )
        {
            return true;
        }
        
        $this->post = $row;
        
        $passed = 0;
        
        //-----------------------------------------
        // Базовые условия
        //-----------------------------------------
        
        #Супермодераторы видят весь скрытый текст
        if( $this->memberData['g_is_supmod'] )
        {
            $passed = 1;
        }
        #Смотрим свой собственный скрытый текст
        elseif( $this->memberData['member_id'] and ($this->memberData['member_id'] == $row['attach_member_id']) )
        {
            $passed = 1;
        }
        
        //-----------------------------------------
        // Указанные пользователем условия
        //-----------------------------------------
        
        else
        {
            
            #Получаем блоки условий
            $blocks = explode(',', $row['attach_pd_conditions']);
            
            #Последовательно проверяем все блоки
            foreach($blocks as $b_id => $block)
            {
                $block_passed = 1;
                
                foreach(explode('+', $block) as $cond)
                {
                    $ret = $this->pdCheckCondition($cond);
                    
                    if( ! $ret['passed'] )
                    {
                        $block_passed = 0;
                    }
                }
                
                #Блок условий успешно выполнен
                if( $block_passed )
                {
                    $passed = 1;
                }
            }
        }
        
        return $passed;
    }
    
    /**
     * Проверить выполнение одного условия
     *
     * @param string $cond - строковое представление условия
     * @return array
     */
    public function pdCheckCondition( $cond )
    {
        $type     = null;
        $passed    = 0;
        $reason    = $this->lang->words['priv_incorrect_condition'];
        $error     = 0;
        
        $cond = trim($cond);
        
        //-----------------------------------------
        // Определяем тип условия
        //-----------------------------------------
        
        if($cond)
        {
            #ID пользователя
            if(is_numeric($cond))
            {
                $type = 'member_id';    
            }
            #Конструкция
            elseif( preg_match("#^([a-z]+)(?:=(.*))?#is", $cond, $match) and array_key_exists($match[1], $this->cond_types) )
            {
                $type = $this->cond_types[$match[1]];
                $cond = $match[2];
            }
            #Имя пользователя
            else
            {
                $type = 'member_name';    
            }
        }
        
        //-----------------------------------------
        // Проверяем условие
        //-----------------------------------------
        
        $func = array($this, 'check_' . $type);
        
        if(is_callable($func))
        {
            list($passed, $reason) = call_user_func($func, $cond);
        }
        else
        {
            $error = 1;
        }
        
        return array( 'type' => $type, 'passed' => $passed, 'reason' => $reason, 'error' => $error );
    }
    
    /**
     * Готовит пост со скрытым текстом для редактирования
     * There is no way we can use just $post['post'] cause of new tricky code from classPost.php
     *
     * Функция сильно полегчала со времен 2.х
     * В общем случае, если мы можем редактировать пост, значит и скрытый текст в нем видим
     *
     * Также предполагается уже инициализированный класс бб-кодов
     *
     * @param    string    $text    - текст поста с указателями
     * @param    array    $post    - массив с постом. Реально нужен только 'private_data'
     * @return     string
     */
    
    public function preEditPrivateData( $text, $post )
    {
        if($post['private_data'])
        {
            foreach($this->_thrawData($post['private_data']) as $pd_id => $pd_data)
            {
                //$pd_data['conditions'] = ($pd_data['conditions'] != $this->settings['priv_default']) ? $pd_data['conditions'] : '';
                $str = implode('|', array($pd_data['conditions'], $pd_data['title'], $pd_data['options']));
                
                #Лень городить код -> убираем пустые секции
                $str = preg_replace('#\|+$#', '', $str);
                
                $text = str_replace('<!--pd_'.$pd_id.'-->', '[' . $this->tag . ($str ? ('=\'' . $str . '\'') : '') . ']' . IPSText::getTextClass('bbcode')->preEditParse($pd_data['text_bbcode']) . '[/'. $this->tag . ']', $text);
            }
        }
        
        return $text;
    }
    
    /**
     * Выцепить скрытый текст из поста и упаковать в 'private_data'
     * Должно вызываться из classPost->compilePostData,
     * т.к. требуется класс бб-кодов с текущими настройками
     *
     * @param    $post
     * @return     array
     */
    public function createPrivateData($post)
    {
        //------------------
        // Пресечь попытки хитрых эксплойтов с аттачами
        //------------------
        
        if(strpos($post['post'], '[attachment=') !== false)
        {
            if(preg_match_all('#\[attachment=(\d+?):#', $post['post'], $out, PREG_PATTERN_ORDER))
            {
                $this->DB->build(array(    'select' => 'attach_id',
                                        'from'   => 'attachments',
                                        'where'  => "attach_id IN('". implode("','", $out[1]) ."') AND attach_pd_conditions!='' AND attach_member_id!='{$this->memberData['member_id']}'",
                                )        );
                $q = $this->DB->execute();
                
                while( $attach = $this->DB->fetch($q) )
                {
                    $post['post'] = str_replace("[attachment={$attach['attach_id']}:", "", $text);
                }
            }
        }
        
        //------------------
        // Экономим ресурсы
        // Не крутим регулярку на обычных постах, коих большинство
        //------------------
        
        if( false === strpos($post['post'], '['.$this->tag) )
        {
            return $post;
        }
        
        //------------------
        // Создаем скрытый текст
        //------------------
        
        $post['post'] = preg_replace_callback( $q = "#(?:\[{$this->tag})=?(?:"|&\#39;)?(.*?)(?:\|(.*?))?(?:\|(.*?))?(?:"|&\#39;)?\](.*?)(?:\[\/{$this->tag}\])#siu", array( &$this, 'process'), $post['post'] );
        
        if( count($this->priv_data) )
        {
            $post['private_data'] = $this->_freezeData($this->priv_data);
        }
        
        return $post;
    }
    
    /**
     * Подготовить превью поста
     * В этой функции хайд всегда будет виден из-за первых двух проверок в showPrivateData
     */
    public function getPostPreview($post)
    {
        return $this->showPrivateData($this->createPrivateData($post));
    }
    
    /**
     * Callback
     *
     * @param    array    $match
     * @return     string    - текстовый указатель
     */
    protected function process($match)
    {
        list($_full, $_cond, $_title, $_opts, $_text) = $match;
        
        //var_dump($match);
        //die();
        
        //-----------------------------------------
        // Проверочки
        //-----------------------------------------
        
        #Вложенный хайд невозможен!
        $needle = '[' . $this->tag;
        if( stristr($_cond, $needle) !== false or stristr($_text, $needle) !== false )
        {
            $this->registry->getClass('output')->showError( 'priv_error_tag_inside' );
        }
        
        #Группы
        if($this->settings['priv_restrict_groups'] and !in_array($this->memberData['member_group'], explode(',', $this->settings['priv_groups'])))
        {
            $this->registry->getClass('output')->showError( 'priv_error_group' );
        }
        
        #Форумы
        if($this->settings['priv_restrict_forums'] and !in_array($this->forum['id'], explode(',', $this->settings['priv_forums'])))
        {
            $this->registry->getClass('output')->showError( 'priv_error_forum' );
        }
        
        #Посты
        if($this->settings['priv_posts'] and $this->memberData['posts'] < $this->settings['priv_posts'])
        {
            $this->registry->getClass('output')->showError( 'priv_error_posts' );
        }
        
        //-----------------------------------------
        // Замена простых числовых условий
        //-----------------------------------------
        
        if($this->settings['priv_replace_numeric'] == 2)
        {
            $_cond = preg_replace('#(^|,)\s*(\d+)\s*(,|$)#is','$1p=$2$3', $_cond);
        }
        elseif($this->settings['priv_replace_numeric'] == 3) //reputation added :)
        {
            $_cond = preg_replace('#(^|,)\s*(\d+)\s*(,|$)#is','$1r=$2$3', $_cond);
        }
        
        //-----------------------------------------
        // Условия по умолчанию
        //-----------------------------------------
        
        $_cond = $_cond ? $_cond : $this->settings['priv_default'];
        
        //-----------------------------------------
        // Title
        //-----------------------------------------
        
        if($_title)
        {
            $_title = IPSText::truncate($_title, 100);    
        }
        
        //-----------------------------------------
        // IMPORTANT: Проверка корректности условий
        //-----------------------------------------
        
        if($this->settings['priv_validate_options'] and ! $this->validateCond($_cond))
        {
            $this->registry->getClass('output')->showError( 'priv_err_condition_1' );
        }
        
        //-----------------------------------------
        // Записать в массив
        //-----------------------------------------
        
        #Чтобы не вызывать парсер лишний раз, мы храним сразу две версии скрытого текста
        #С бб-кодами - для редактирования
        #С html-кодом, для отображения
        #В версии 1.2 добавлены опции и title
        $this->priv_data[] = array(    'conditions'    => $_cond,
                                    'options'        => $_opts,
                                    'title'            => $_title,
                                    'text_bbcode'    => $_text,
                                    'text_parsed'    => IPSText::getTextClass( 'bbcode' )->preDisplayParse( $_text ),
                                    );
                                    
        //-----------------------------------------
        // Обработать аттачи внутри скрытого текста
        //-----------------------------------------
        
        if(strpos($_text, '[attachment=') !== false)
        {
            if(preg_match_all('#\[attachment=(\d+?):#', $_text, $out, PREG_PATTERN_ORDER))
            {
                $this->DB->update('attachments', array('attach_pd_conditions' => $_cond), "attach_id IN ('". implode("','", $out[1]) ."') AND attach_member_id='{$this->memberData['member_id']}'");
            }
        }
        
        #Не превысили ли ограничение по кол-ву?
        if($this->settings['priv_max_number'] and count($this->priv_data) > $this->settings['priv_max_number'])
        {
            $this->registry->getClass('output')->showError( array( 'priv_error_max_number', intval($this->settings['priv_max_number']) ) );
        }
        
        #Возвращаем указатель
        return '<!--pd_'. (count($this->priv_data) - 1) .'-->';
    }
    
    /**
     * Проверить валидность условий
     */
    protected function validateCond($str)
    {
        #Получаем блоки условий
        $blocks = explode(',', $str);
        
        #Последовательно проверяем все блоки
        foreach($blocks as $b_id => $block)
        {
            foreach(explode('+', $block) as $cond)
            {
                $ret = $this->pdCheckCondition($cond);
                
                if( $ret['error'] )
                {
                    return false;
                }
            }
        }
        
        return true;
    }
    
    /**
     * ID пользователя
     */
    protected function check_member_id($val)
    {
        if( intval($val) == $this->memberData['member_id'] )
        {
            $passed = 1;
        }
        
        $reason = sprintf($this->lang->words['priv_reason_member_id'], $val);
        
        return array($passed, $reason);
    }
    
    /**
     * Имя пользователя
     */
    protected function check_member_name($val)
    {
        if($this->memberData['member_id'] and !is_numeric($val) and $val == $this->memberData['members_display_name'])
        {
            $passed = 1;
        }
        
        $reason = sprintf($this->lang->words['priv_reason_member_name'], $val);
        
        return array($passed, $reason);
    }
    
    /**
     * Регистрация
     */
    protected function check_reg($val)
    {
        if($this->memberData['member_id'] and $this->memberData['member_group'] != $this->settings['auth_group'])
        {
            $passed = 1;
        }
            
        $reason = sprintf($this->lang->words['priv_reason_reg'], $this->base_url);
        
        return array($passed, $reason);
    }
    
    /**
     * Группа
     */
    protected function check_group($val)
    {
        //var_dump($val, $this->memberData);
        #By id?
        if(is_numeric($val) and $this->memberData['member_group_id'] == $val)
        {
            $passed = 1;
        }
        #By title?
        elseif(!is_numeric($val) and $this->memberData['g_title'] == $val)
        {
            $passed = 1;
        }
        //var_dump($this->caches['group_cache']);
        $g_title = is_numeric($val) ? $this->caches['group_cache'][$val]['g_title'] : $val;
        
        $reason = sprintf($this->lang->words['priv_reason_group'], $g_title);
        
        return array($passed, $reason);
    }
    
    /**
     * Посты
     */
    protected function check_posts($val)
    {
        if($this->memberData['posts'] >= $val)
        {
            $passed = 1;
        }
        else
        {
            $remains = sprintf($this->lang->words['priv_remains'], $val - $this->memberData['posts']);
        }
        
        $reason = sprintf($this->lang->words['priv_reason_posts'], $val) . $remains;
        
        return array($passed, $reason);
    }
    
    /**
     * Репутация
     */
    protected function check_rep($val)
    {
        if($val and $this->memberData['pp_reputation_points'] >= $val) //points
        {
            $passed = 1;
        }
        elseif(!$val and isset($this->post['has_given_rep']) and $this->post['has_given_rep'] == '1') //like old 'thanks' :)
        {
            $passed = 1;
        }
        
        if($val)
        {
            $remains = sprintf($this->lang->words['priv_remains'], $val - $this->memberData['pp_reputation_points']) . $remains;
            $reason = sprintf($this->lang->words['priv_reason_rep_points'], $val) . $remains;
        }
        else
        {
            $reason = $this->lang->words['priv_reason_rep'];
        }
        
        return array($passed, $reason);
    }
    
    protected function _freezeData($data)
    {
        return is_array($data) ? serialize($data) : null;
    }
    
    protected function _thrawData($data)
    {
        $data = unserialize($data);
        return is_array($data) ? $data : array();
    }
}
?>
[/spoiler]
Вот код, который как раз отвечает за создание тега и его работу:
[spoiler="код создание тега"]
    $post['post'] = preg_replace_callback( $q = "#(?:\[{$this->tag})=?(?:"|&\#39;)?(.*?)(?:\|(.*?))?(?:\|(.*?))?(?:"|&\#39;)?\](.*?)(?:\[\/{$this->tag}\])#siu", array( &$this, 'process'), $post['post'] );
[/spoiler]
Вот код, который отвечает за редактирование:
[spoiler="редактирование"]
                $text = str_replace('<!--pd_'.$pd_id.'-->', '[' . $this->tag . ($str ? ('=\'' . $str . '\'') : '') . ']' . IPSText::getTextClass('bbcode')->preEditParse($pd_data['text_bbcode']) . '[/'. $this->tag . ']', $text);
[/spoiler]
Если убрать кавычки, то они не будут подставляться при редактировании:
[spoiler="редактирование2"]
                $text = str_replace('<!--pd_'.$pd_id.'-->', '[' . $this->tag . ($str ? ('=' . $str . '') : '') . ']' . IPSText::getTextClass('bbcode')->preEditParse($pd_data['text_bbcode']) . '[/'. $this->tag . ']', $text);
[/spoiler]

Но изначально при создании кавычки все равно добавляются, где они могут быть здесь:
[spoiler="дважды quot и 39"]
    $post['post'] = preg_replace_callback( $q = "#(?:\[{$this->tag})=?(?:"|&\#39;)?(.*?)(?:\|(.*?))?(?:\|(.*?))?(?:"|&\#39;)?\](.*?)(?:\[\/{$this->tag}\])#siu", array( &$this, 'process'), $post['post'] );
[/spoiler]

Регулярку на 100% не расшифровал, вижу ASCII = $quot; ' если их удалю, то сам тег создается, но кавычки все равно остаются.
Пробовал перед этой регуляркой написать свою, чтобы кавычки удаляло, но код перестает работать (скорее мой preg-replace не правильный, но если что его потом обсудим).

Сейчас проблема: убрать кавычки при создании hide.

з.ы. в хуке еще есть файлы .xml, по моему мнению там ничего из проблемы нет, но если - могу выложить все файлы, или хук архивом.
Тому кто поможет - денежное вознаграждение :)


--------------------
0
Вернуться в начало страницы
 
Ответить с цитированием данного сообщения
sc2r2bey
sc2r2bey
сообщение 5.10.2016, 0:16; Ответить: sc2r2bey
Сообщение #2


сложно по яйцам определить птицу, но навскидку, за вывод скрытого сообщения отвечает вот этот блок:
else
         {
            switch($this->settings['priv_hide_mode'])
            {
               case 1:
                  $replacer = '';
                  break;
               case 2:
               default:
                  $replacer = $this->registry->getClass('output')->getTemplate('private_data')->private_data_closed( $data, $ret_conds );
                  break;
            }
            
            $row['post'] = str_replace('<!--pd_'.$id.'-->', $replacer, $row['post']);
         }
      }


разберись что идет и откуда

Замечание модератора:
Эта тема была закрыта автоматически ввиду отсутствия активности в ней на протяжении 100+ дней.
Если Вы считаете ее актуальной и хотите оставить сообщение, то воспользуйтесь кнопкой
или обратитесь к любому из модераторов.


--------------------
Заметки о разработке и не только
программирую web и для we
Вернуться в начало страницы
 
Ответить с цитированием данного сообщения
Открыть тему
Тема закрыта
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0


Свернуть

> Похожие темы

  Тема Ответов Автор Просмотров Последний ответ
Открытая тема (нет новых ответов) SEO-текст на главной странице сайта и в категориях
5 boltuk 1426 26.3.2024, 21:43
автор: c4p1t4l15t
Открытая тема (нет новых ответов) Можно ли в старый SEO текст вместо старого домена поставить новый?
3 Tutich 1215 22.3.2024, 14:47
автор: Tutich
Открытая тема (нет новых ответов) Крауд-маркетинг который работает | Эффективные Ру-ссылки
1 Azyuka 1055 13.2.2024, 19:36
автор: tascha56
Горячая тема (нет новых ответов) Текст для сайта на английском языке
33 D007user 18106 26.1.2022, 17:16
автор: D007
Горячая тема (нет новых ответов) Копирайтинг и рерайт: качественный сео-текст по доступной цене!
374 Sostavitel 196983 18.1.2022, 23:46
автор: Sostavitel


 



RSS Текстовая версия Сейчас: 20.4.2024, 9:06
Дизайн