1. Приветствуем Вас на неофициальном форуме технической поддержки XenForo на русском языке. XenForo - коммерческий форумный движок от бывших создателей vBulletin, написанный на PHP.

Программное создание тем и сообщений на форуме

Тема в разделе "Статьи по XenForo Framework", создана пользователем FractalizeR, 17.10.2010.

Загрузка
  1. GERAsimov

    GERAsimov Новичок

    Регистрация:
    02.09.16
    Сообщения:
    8
    Симпатии:
    0
    Версия XF:
    1.5.9
    А как автоматом получать имя username имея только user_id ?
     
  2. infis

    infis Местный

    Регистрация:
    27.06.11
    Сообщения:
    5 966
    Симпатии:
    3 548
    Версия XF:
    1.5.9
    Примерно так:
    PHP:
    $userModel XenForo_Model::create('XenForo_Model_User');
    $user $userModel->getUserById($user_id);
    $username $user['username'];
     
    GERAsimov нравится это.
  3. GERAsimov

    GERAsimov Новичок

    Регистрация:
    02.09.16
    Сообщения:
    8
    Симпатии:
    0
    Версия XF:
    1.5.9
    Здорово! Все работает. Подставил правки в предыдущий вариант кода и теперь зная только id пользователя постим.
     
  4. GERAsimov

    GERAsimov Новичок

    Регистрация:
    02.09.16
    Сообщения:
    8
    Симпатии:
    0
    Версия XF:
    1.5.9
    Может еще кто подскажет если посте есть картинка или атач.... Как передавать это через DataWriter ?
     
  5. GERAsimov

    GERAsimov Новичок

    Регистрация:
    02.09.16
    Сообщения:
    8
    Симпатии:
    0
    Версия XF:
    1.5.9
    Подскажите, пожалуйста, При создании темы вышеизложенным скриптом можно ли сразу создавать создавать метку для тему ?
    Благодарю.
     
  6. Ulibka

    Ulibka Активный пользователь

    Регистрация:
    02.11.17
    Сообщения:
    16
    Симпатии:
    0
    Версия XF:
    1.5.15
    Подскажите пожалуйста как программно создать node (раздел) ?
     
  7. infis

    infis Местный

    Регистрация:
    27.06.11
    Сообщения:
    5 966
    Симпатии:
    3 548
    Версия XF:
    1.5.9
    Проще всего посмотреть код в контроллере и взять его за основу.
     
  8. Ulibka

    Ulibka Активный пользователь

    Регистрация:
    02.11.17
    Сообщения:
    16
    Симпатии:
    0
    Версия XF:
    1.5.15
    Спасибо за направление поиска :)

    Нет ли чего нибудь готового как в 1 посте:
    $newThread = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread');
     
  9. infis

    infis Местный

    Регистрация:
    27.06.11
    Сообщения:
    5 966
    Симпатии:
    3 548
    Версия XF:
    1.5.9
    Благодарите за направление и даже не пытаетесь им воспользоваться. Ладно, еще один пинок в данном направлении: в контроллере XenForo/ControllerAdmin/Forum смотреть actionSave. Дальше уж сами разбирайтесь. Если не можете разобраться, то наймите программиста. Кстати, на офе все также проигнорировали на аналогичный вопрос.
     
    Ulibka нравится это.
  10. Ulibka

    Ulibka Активный пользователь

    Регистрация:
    02.11.17
    Сообщения:
    16
    Симпатии:
    0
    Версия XF:
    1.5.15
    Пытаюсь перенести на Xenforo данные с другого форума.
    Пользователей создал, топики записал, ноды записал руками, а вот с сообщениями беда...

    Проблема заключается в том, что сообщений порядка 1 млн.
    Я их закинул в рядом лежащую базу mysql и начинаю записывать сообщения способом, который указан в данной ветке.
    Проблема заключается в том, что 10тыс. сообщений записывается порядка 15 минут, соответственно свой 1 млн. я запишу ближе к своей смерти :)

    На первый взгляд сообщения кладутся в таблицу xf_post с простой структурой.
    Код Xenforo я пристально не смотрел, но на вскидку там выполняется масса дополнительных операций.

    Можете подсказать, что будет если я сообщения закину в таблицу xf_post ?

    Может быть у Xenforo есть какая то утилита, которая восстанавливает его базу ?

    Вот код, которым я пользуюсь:
    PHP:
    <html lang="ru-RU">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <body> \n

    <?php
              

    $mysqli 
    = new mysqli('localhost''bulka''bulka''woodtools');
    // Настройка подключения к базе данных
    $mysqli->query('SET names "utf8"');     
    setlocale(LC_ALL'ru_RU.65001''rus_RUS.65001''Russian_Russia. 65001''russian');

    // Выполняем запрос SQL
        
    $sql "SELECT TopicID_XF,Автор_XF_ID,username,MessageHTML,message_id,Message_ID_XF,id1 FROM woodtools.messages where id1 between 20001 and 30000 and Message_ID_XF is null ";     


    $result $mysqli->query($sql);
    if (
    $result->num_rows === 0) {
        
    // Упс! в запросе нет ни одной строки! Иногда это ожидаемо и нормально, иногда нет.
        // Решать Вам. В данном случае, может быть actor_id был слишком большим?
        
    echo "Мы не смогли найти совпадение для , попробуйте еще раз.";
        exit;
    }

    //Список полей, которые можно установить через DataWriter можно посмотреть по полям таблицы xf_users в базе данных форума.
    //__DIR__    Директория файла. Если используется внутри подключаемого файла, то возвращается директория этого файла.
    //Это эквивалентно вызову dirname(__FILE__). Возвращаемое имя директории не оканчивается на слеш, за исключением корневой директории.
    require(__DIR__ '/../library/XenForo/Autoloader.php');
    //Тоже самое для 2й версии
    //$dir = __DIR__;
    //require($dir . '/src/XF.php');
    set_time_limit(0);
    XenForo_Autoloader::getInstance()->setupAutoloader(__DIR__ '/../library');

    $startTime microtime(true);
    XenForo_Application::initialize(__DIR__ '/../library'__DIR__ '/../');
    XenForo_Application::set('page_start_time'$startTime);
    XenForo_Application::disablePhpErrorHandler();
          
          
    while (
    $row $result->fetch_assoc()) {
     

         
    $userId=$row["Автор_XF_ID"];   
         
    $userName=$row["username"];         
         
    $threadId=$row["TopicID_XF"];     
         
    $message=$row["MessageHTML"]; 
         echo    
    $userName " - " .  $threadId "<p>";
     

      
          
    $newPost XenForo_DataWriter::create('XenForo_DataWriter_DiscussionMessage_Post');
           
    $newPost->set('user_id'$userId);
           
    $newPost->set('username'$userName);
           
    $newPost->set('message'XenForo_Helper_String::autoLinkBbCode($message));
           
    $newPost->set('thread_id'$threadId);
           
    $newPost->preSave();
           if (!
    $newPost->hasErrors())
           {
               
    $newPost->save(); 
               
    $XF_postid=$newPost->get('post_id'); 
              
                
    $sql "UPDATE woodtools.messages SET Message_ID_XF=" $XF_postid " where id1=" $row['id1'];       
                  echo 
    $sql "<p>";
                  
    $mysqli->query($sql);
                  echo 
    "топик сохранен <p>" ;
           } else
           {
                foreach (
    $newPost->getErrors() as $threadError) {
                    echo 
    $threadError "<p>";
                }
           }



    }
        
        
        
    // Скрипт автоматически закрывает соединение MySQL и освобождает память, тем не
    //менее давайте сделаем это вручную
    $result->free();
    $mysqli->close();         

    ?>   
    Импорт завершен
    </body></html>
     
  11. infis

    infis Местный

    Регистрация:
    27.06.11
    Сообщения:
    5 966
    Симпатии:
    3 548
    Версия XF:
    1.5.9
    Возьмите какой-нибудь штатный импорт и на его основе сделайте свой. Это будет наиболее грамотным решением. И по производительности будет хорошо работать.
     
  12. Ulibka

    Ulibka Активный пользователь

    Регистрация:
    02.11.17
    Сообщения:
    16
    Симпатии:
    0
    Версия XF:
    1.5.15
    Вот код с помощью которого мне удалось записать node.
    Первый дерево забиавал руками.
    Во второй раз (базу обнулил) сил не хватило.

    Все проводилось на полностью пустой базе.

    Чтобы все работало надо создать соответствующие записи в таблице xf_forum

    insert into xf_forum (node_id,prefix_cache)
    select node_id,'' from xf_node

    xf_node связана с таблицей xf_forum.
    Топиков на момент заливки не было ни одного.

    Тут идут 3 одинаковых куска - у меня дерево из 3 уровней, можно организовать цикл. :)


    PHP:
    <?php
        


    $mysqli 
    = new mysqli('localhost''bulka''bulka''woodtools');
    // Настройка подключения к базе данных
    $mysqli->query('SET names "utf8"'); 
    // Настройка локали
    setlocale(LC_ALL'ru_RU.65001''rus_RUS.65001''Russian_Russia. 65001''russian');

    // Выполняем запрос SQL
    $sql "SELECT * FROM   woodtools.board_wt where depth=0";
    if (!
    $result $mysqli->query($sql)) {
        
    // О нет! запрос не удался.
        
    echo "Извините, возникла проблема в работе сайта.";

        
    // И снова: не делайте этого на реальном сайте, но в этом примере мы покажем,
        // как получить информацию об ошибке:
        
    echo "Ошибка: Наш запрос не удался и вот почему: \n";
        echo 
    "Запрос: " $sql "\n";
        echo 
    "Номер_ошибки: " $mysqli->errno "\n";
        echo 
    "Ошибка: " $mysqli->error "\n";
        exit;
    }     

    if (
    $result->num_rows === 0) {
     
        echo 
    "Мы не смогли найти совпадение для $aid, простите. Пожалуйста, попробуйте еще раз.";
        exit;
    }

    require(
    __DIR__ '/../library/XenForo/Autoloader.php');

    set_time_limit(0);

    XenForo_Autoloader::getInstance()->setupAutoloader(__DIR__ '/../library');

    $startTime microtime(true);
    XenForo_Application::initialize(__DIR__ '/../library'__DIR__ '/../');
    XenForo_Application::set('page_start_time'$startTime);
    XenForo_Application::disablePhpErrorHandler();
                
        
    /** @var XenForo_DataWriter_User $writer */
      
                                                                        
      
    while ($row $result->fetch_assoc()) {
        
    $writer XenForo_DataWriter::create('XenForo_DataWriter_Node');         

        
    $writer->set('title',$row["BoardName"]);
        if (   
    $row["BoardComment"] != null ) {     $writer->set('description',$row["BoardComment"]); }
           
    $writer->set('node_type_id',  'Forum');
        
    $writer->set('parent_node_id',  0);
      
        
    //var_dump($writer);
    //    print_r($writer);   
      
      
        
    $writer->preSave();
         if (!
    $writer->getErrors())
        {
          
    $writer->save(); 
          
    $bdrnew $writer->getMergedData();
          
    $sql "UPDATE board_wt SET BoardID_XF=" $bdrnew['node_id'] . " where id=" $row['id'];     
          
    $mysqli->query($sql);             
          echo 
    "сохранено \n<p>"  ;   
        } 
        
    }           

    $sql ="UPDATE woodtools.board_wt INNER JOIN woodtools.board_wt AS Board_1 ON board_wt.ParentId1 = Board_1.BoardID SET board_wt.ParentId_XF = Board_1.BoardID_XF WHERE (board_wt.depth=1) AND (Board_1.depth=0)";

    $mysqli->query($sql);
    echo 
    "update прошел ";     


    $sql "SELECT * FROM   woodtools.board_wt where depth=1";
    $result $mysqli->query($sql); 


      
    while (
    $row $result->fetch_assoc()) {
        
    $writer XenForo_DataWriter::create('XenForo_DataWriter_Node');         

        
    $writer->set('title',$row["BoardName"]);
        if (   
    $row["BoardComment"] != null ) {     $writer->set('description',$row["BoardComment"]); }
           
    $writer->set('node_type_id',  'Forum');
        
    $writer->set('parent_node_id',  $row["ParentId_XF"]);
     
      
        
    $writer->preSave();
         if (!
    $writer->getErrors())
        {
          
    $writer->save(); 
          
    $bdrnew $writer->getMergedData();
          
    $sql "UPDATE board_wt SET BoardID_XF=" $bdrnew['node_id'] . " where id=" $row['id'];     
          
    $mysqli->query($sql);             
          echo 
    "сохранено \n<p>"  ;   
        } 
        
    }       

     

    $sql ="UPDATE woodtools.board_wt INNER JOIN woodtools.board_wt AS Board_1 ON board_wt.ParentId1 = Board_1.BoardID SET board_wt.ParentId_XF = Board_1.BoardID_XF WHERE (board_wt.depth=2) AND (Board_1.depth=1)";
    $mysqli->query($sql);
    echo 
    "update прошел ";     


    $sql "SELECT * FROM   woodtools.board_wt where depth=2";
    $result $mysqli->query($sql);

      
    while (
    $row $result->fetch_assoc()) {
        
    $writer XenForo_DataWriter::create('XenForo_DataWriter_Node');         

        
    $writer->set('title',$row["BoardName"]);
        if (   
    $row["BoardComment"] != null ) {     $writer->set('description',$row["BoardComment"]); }
           
    $writer->set('node_type_id',  'Forum');
        
    $writer->set('parent_node_id',  $row["ParentId_XF"]);
     
      
        
    $writer->preSave();
         if (!
    $writer->getErrors())
        {
          
    $writer->save(); 
          
    $bdrnew $writer->getMergedData();
          
    $sql "UPDATE board_wt SET BoardID_XF=" $bdrnew['node_id'] . " where id=" $row['id'];     
          
    $mysqli->query($sql);             
          echo 
    "сохранено \n<p>"  ;   
        } 
        
    }       
     


    ?>
     
  13. Ulibka

    Ulibka Активный пользователь

    Регистрация:
    02.11.17
    Сообщения:
    16
    Симпатии:
    0
    Версия XF:
    1.5.15
    Однако я поторопился :)
    После программной записи дерево в админке отображается нормально, а вот когда переходишь в обычный интерфейс пользователя - все разделы форумов идут вместе без подфорумов.

    Через админку пересаживаю node forum на другого родителя - все равно отображается на главной.
    Никто не знает - можно ли с этим бороться ?

    Смотрел таблицу xf_node - часть binary у детей пишется похоже на правду.
     
  14. infis

    infis Местный

    Регистрация:
    27.06.11
    Сообщения:
    5 966
    Симпатии:
    3 548
    Версия XF:
    1.5.9
    Дам только один совет. Сделайте всё через штатные методы. Не нужно что-то делать через штатные методы, а что-то на чистом SQL. Еще раз посмотрите внимательно на штатные импортеры. Оттуда можно взять 95% кода и добавить немного своего.
     
    ~1~ нравится это.
  15. Ulibka

    Ulibka Активный пользователь

    Регистрация:
    02.11.17
    Сообщения:
    16
    Симпатии:
    0
    Версия XF:
    1.5.15
    Помогите пожалуйста - не удается задать дату первого сообщения при создании новой темы.
    Соответственно следом за ней не проходит запись старого поста.

    После записи темы с первым постом по такому коду дата первого поста устанавливается на текущую дату/время.

    Код:
     $message_date=strtotime('2016-1-9 10:00');
     
         $writer = XenForo_DataWriter::create( 'XenForo_DataWriter_Discussion_Thread' );
            $writer->bulkSet( [
                'user_id'          => $userId,
                'username'         => $userName ,
                'title'            => $title,
                'node_id'          => $nodeId,
            ] );
            $postWriter = $writer->getFirstMessageDw();
            $postWriter->set( 'message', $message );
            $postWriter->set('post_date',$message_date);
     
  16. infis

    infis Местный

    Регистрация:
    27.06.11
    Сообщения:
    5 966
    Симпатии:
    3 548
    Версия XF:
    1.5.9
    Так Вы попробуйте сразу задать в bulkSet в том числе параметр 'post_date'. Тогда и тема и первый пост должны будут создаться с заданной датой. А попытка установить дату через получение первого поста будет уже бесполезной, так как ксен будет игнорировать установку этого поля после сохранения темы.
     
    Ulibka нравится это.
  17. Ulibka

    Ulibka Активный пользователь

    Регистрация:
    02.11.17
    Сообщения:
    16
    Симпатии:
    0
    Версия XF:
    1.5.15
    infis, низкий Вам поклон и огромное спасибо!!!
    Все работает!
    Я с датой сообщения до Вашего совета полдня извращался - но так ничего и не придумал.
     
  18. Light4D

    Light4D Новичок

    Регистрация:
    16.01.18
    Сообщения:
    2
    Симпатии:
    0
    Версия XF:
    1.5.14
    А как перевести HTML код поста в BB-код xenforo'вский?
     
  19. Ulibka

    Ulibka Активный пользователь

    Регистрация:
    02.11.17
    Сообщения:
    16
    Симпатии:
    0
    Версия XF:
    1.5.15
    Я когда переводил форум из SMF в XF пришлось написать парсер потому что доступа к базе не было.
    В рамках парсера я разбирал текст сообщений и переводил в BB cod.

    Т.е. под Вашу задачу надо писать отдельный парсер HTML, который это сделает.
     
  20. infis

    infis Местный

    Регистрация:
    27.06.11
    Сообщения:
    5 966
    Симпатии:
    3 548
    Версия XF:
    1.5.9
    Не совсем. В ксене есть парсер HTML, который переводит в бб-код. Он применяется при вставке HTML в текст сообщения. Можно попробовать использовать его.
     

Поделиться этой страницей