Разделы

  
 

Дополнение - социальная сеть на MODx Evo

Добрый день всем.
В процессе разработки одного из проектов появилось большое желание выбросить весь огород из webloginpe+FDM+самописные скрипты, на которых ворочался функционал user-generated content и реализовать с нуля компонент, реализующий некоторый функционал, присущий социальным сетям.
Сейчас пользовательский контент — это ресурсы в дереве modx, находящиеся в определенных папках и со строго определенными шаблонами.

Структура расширения предполагается такой:
— Класс, с экземпляром $modx->social который создается по OnLoadWebPage и доступен всегда и везде, на манер $modx->db.
— Модуль, в котором производится конфигурация этого расширения и в котором можно наблюдать и вмешиваться в пользовательскую активность
— Набор сниппетов, реализующих различные аспекты соц.сети через объект $modx->social (сниппет регистрации, личного кабинета, редактора контента, вывода топа пользователей, и т.д.)

На данный момент (25.11.2011) запланировано и отчасти реализовано:
— Скелет класса
— Настройка политик для различных веб-групп пользователей по созданию/редактированию пользовательского контента
— Методы для отрисовки формы редактирования контента и сохранения с проверкой на соответствие правам текущего веб-пользователя
— Обязательно будут способы управления пользовательскими файлами (некая замена админскому MCPuk для фронтенда)
— Политики для групп пользователей сейчас имеют такой вид:
web-группа => шаблоны, с которыми разрешено создавать документы + описание родительских документов, где пользовательский контент разрешено создавать

Также будет сделан нормальный человеческий личный кабинет + вывод списков пользвательских документов с кнопками для редактирования. Все это будет ворочаться с использованием шаблонов на чанках и с единой конфигурацией, которая пока неизвестно где будет храниться, и настраиваться из своего модуля.

И еще планируется переключатель — хранить весь пользовательский контент в таблицах modx или в собственных таблицах (именно он позволит создать сайт из сотен тысяч ресурсов, который не будет тормозить :)).

Что очень лень делать:
— списки друзей + настройки приватностей (иными словами функционал Вконтакте)))
— личные сообщения
— управление аватарками
— всевозможные рейтинги пользователей, блогов и кармы
— комментирование и оценка всего и вся (но в минимальном наборе будет сделано)

В этом топике хотелось бы услышать пожелания по функционалу и может быть собрать какие-то наработки, которые позволят ускорить разработку дополнения.
А может соц.сеть на modx вообще никому не нужна, и стоит ограничиться только минимально необходимым фунционалом для user-generated-content?

Формирование формы для фронт-енд редактирования контента

Сниппет основан на механизмах MODx для формирования страницы редактирования в /manager/ и использует функции из соответствующих файлов. Код сниппета [[fdm_form_render]]:

<?php
global $modx;

// &id
// &tpl
// &hide : 'name_of_tv1,name_of_tv2'
// &add  : 'pagetitle,alias,parent'

if($hide) $hide = explode(',',$hide);
if(!$tpl) $tpl = intval($_GET['tpl']);
if($id && !$tpl)
{
    $tplidc = $modx->db->select('template','modx_site_content','id = '.intval($id));
    $tplidc = $modx->db->makeArray($tplidc);
    $tpl = $tplidc[0]['template'];
} 
    
$tvs = $modx->db->select('tmplvarid,rank','modx_site_tmplvar_templates','templateid = '.intval($tpl),'rank' );
$tvs = $modx->db->makeArray($tvs);
//print_r($tvs);

echo '<tr style="display:none;"><td colspan="2">';
echo '<input type="hidden" name="template" value="'.$tpl.'" /> ';
echo '</td></tr>';

// $new_id = $modx->db->getValue( $modx->db->query('SELECT `id` FROM `modx_site_content` ORDER BY `id` DESC limit 1') );
$r = $modx->db->getRow( $modx->db->query("SHOW TABLE STATUS LIKE 'modx_site_content'") );
$new_id = $r['Auto_increment'];

if(strpos(','.$add.',', ',alias,')!==false) {
  echo '    <tr>
        <td><!-- label for="alias" class="title">Псевдоним</label --></td>
        <td><input name="alias" id="alias" value="'.$new_id.'" type="hidden" /></td>
    </tr>';
}

///////////////////

// Get table names (alphabetical)
$tbl_active_users               = $modx->getFullTableName('active_users');
$tbl_categories                 = $modx->getFullTableName('categories');
$tbl_document_group_names       = $modx->getFullTableName('documentgroup_names');
$tbl_member_groups              = $modx->getFullTableName('member_groups');
$tbl_membergroup_access         = $modx->getFullTableName('membergroup_access');
$tbl_document_groups            = $modx->getFullTableName('document_groups');
$tbl_keyword_xref               = $modx->getFullTableName('keyword_xref');
$tbl_site_content               = $modx->getFullTableName('site_content');
$tbl_site_content_metatags      = $modx->getFullTableName('site_content_metatags');
$tbl_site_keywords              = $modx->getFullTableName('site_keywords');
$tbl_site_metatags              = $modx->getFullTableName('site_metatags');
$tbl_site_templates             = $modx->getFullTableName('site_templates');
$tbl_site_tmplvar_access        = $modx->getFullTableName('site_tmplvar_access');
$tbl_site_tmplvar_contentvalues = $modx->getFullTableName('site_tmplvar_contentvalues');
$tbl_site_tmplvar_templates     = $modx->getFullTableName('site_tmplvar_templates');
$tbl_site_tmplvars              = $modx->getFullTableName('site_tmplvars');

///////////////////

$docgrp = ''; //implode(',', $_SESSION['mgrDocgroups']);

$replace_richtexteditor = array(
                    'ta',
                );

$template = $tpl;

                $sql = 'SELECT DISTINCT tv.*, IF(tvc.value!=\'\',tvc.value,tv.default_text) as value '.
                       'FROM '.$tbl_site_tmplvars.' AS tv '.
                       'INNER JOIN '.$tbl_site_tmplvar_templates.' AS tvtpl ON tvtpl.tmplvarid = tv.id '.
                       'LEFT JOIN '.$tbl_site_tmplvar_contentvalues.' AS tvc ON tvc.tmplvarid=tv.id AND tvc.contentid=\''.$id.'\' '.
                       'LEFT JOIN '.$tbl_site_tmplvar_access.' AS tva ON tva.tmplvarid=tv.id '.
                       'WHERE tvtpl.templateid=\''.$template.'\' ORDER BY tvtpl.rank,tv.rank';
                $rs = mysql_query($sql);
                $limit = mysql_num_rows($rs);
                if ($limit > 0) {
//                    echo "\t".'<table class="fdm_tvs" border="0" cellspacing="0" cellpadding="0">'."\n";
                    require_once(MODX_MANAGER_PATH.'includes/tmplvars.inc.php');
                    require_once(MODX_MANAGER_PATH.'includes/tmplvars.commands.inc.php');
                    for ($i = 0; $i < $limit; $i++) { 
                        // Go through and display all Template Variables
                        $row = mysql_fetch_assoc($rs);
                        if( is_array($hide) && in_array($row['name'],$hide) ) continue;
                        
                        if ($row['type'] == 'richtext' || $row['type'] == 'htmlarea') {
                            // Add richtext editor to the list
                            if (is_array($replace_richtexteditor)) {
                                $replace_richtexteditor = array_merge($replace_richtexteditor, array(
                                    "tv" . $row['id'],
                                ));
                            } else {
                                $replace_richtexteditor = array(
                                    "tv" . $row['id'],
                                );
                            }
                        }
                        // splitter
                        if ($i > 0 && $i < $limit)
                            echo "\t\t",'<tr><td colspan="2"><div class="split"></div></td></tr>',"\n";

                        $tvPBV = array_key_exists('tv'.$row['id'], $_POST) ? $_POST['tv'.$row['id']] : $row['value']; // post back value
                        $field_html = renderFormElement($row['type'], $row['name'], $row['default_text'], $row['elements'], $tvPBV); // , ' style="width:300px;"'
                        
                        echo '<tr><td class="label"><p class="title">',$row['caption'],"</p>\n",
                             '<p class="comment">',$row['description'],"</p></td>\n",
                             '<td class="field">',"\n",
                             $field_html,"\n",
                             "</td></tr>\n";
                    }
//                    echo "\t</table>\n";
                } else {
                    // There aren't any Template Variables
                    echo "Нет tv-параметров\n";
                }
//echo "</table>\n";
?>


Для использования, нужно вызвать сниппет в чанке с шаблоном формы FDM, указав требуемый номер шаблона. Также можно указать tv-параметры, которые нужно исключить из формы:

<form method="post" action="[[get?name=`$uri`]]"  id="fdmForm"> 
<fieldset> 
 
    <input type="hidden" name="formid" value="fdmForm" /> 
    <input type="hidden" name="fdmid" value="[[get?&name=`fdmid`]]" eform="::0::" /> 
...
[[fdm_form_render? &id=`[+id+]` &tpl=`[[get?name=`tplid`]]` &hide=`user_id,icon,mg_type` ]]
...
</fieldset> 
</form> 


Сниппет выводит только tv-параметры! Стандартные, такие как заголовок, аннотацию, дату публикации и т. д. он не возвращает.

UPD: Добавил скриншот личного кабинета одного из сайтов: