Новости Joomla

👩‍💻 ИИ-админ для Joomla ближе, чем вы думаете: Joomla MCP.

👩‍💻 ИИ-админ для Joomla ближе, чем вы думаете: Joomla MCP.

В февральском номере Joomla Community Magazine в статье Evolving Joomla - Joomla CMS MCP Server: Opening the Door to AI-Powered Administration рассказывается о работе команды разработчиков над внедрением в ядро Joomla MCP-сервера.

Что такое MCP-сервер?
Последние годы всех захватывает бум ИИ-технологий. Появились ИИ-агенты - программы, устанавливаемые на сервер или компьютер, которые получают от вас запрос или задачу в человеческом виде и могут выполнять действия с файлами, ходить по сайтам, создавать сайты, программировать и т.д. Люди используют ИИ-агентов в самых разных ситуациях: от написания и проверки кода (даже там, где язык программирования не знаете совсем) до планирования путешествий и бронирования гостиницы.

ИИ-агенты могут использовать различные программные инструменты по протоколу Model Context Protocol (MCP). Для этого разработчик программы должен внедрить MCP в свой продукт или сервис. Так, например, ваш ИИ-агент может ходить по сайтам через браузер и собирать нужную информацию, управляя браузером через MCP-сервер. Или использовать функционал IDE PHP Storm для написания кода, сбора и отладки ошибок, использовать поиск PHP Storm по кодовой базе, а не простой текстовый поиск по файлам. MCP предоставляет набор функций для полноценного управления программным обеспечением.

В случае с Joomla, сервер MCP может предоставить администраторам следующие возможности:
- Автоматическое создание категорий, материалов и меню на основе карты сайта или PDF-файла.
- Создавайть SEO-оптимизированные заголовки и метаописания в пакетном режиме.
- Обновлять расширения на нескольких сайтах одновременно
- Создание посадочные страницы.

Важно отметить, что сервер MCP не задумывался как функция, доступная только «супер-администраторам». Цель инициативы — создать решение, которое будет простым в настройке, маломощным и доступным для широкого круга пользователей.

В процессе разработки точка входа Joomla (аналогично Site, Administrator, Api, Cli), которая будет работать с Streamable HTTP, необходимым для MCP. Аутентификация пока что предполагается на токенах, но затем планируется создание универсального OAuth-сервера для Joomla.
Фактические возможности MCP — инструменты, ресурсы и подсказки — реализованы в виде плагинов для обеспечения расширяемости. Таким образом ожидаем, что и сторонние разработчики смогут создавать MCP-плагины для внедрения поддержки своих расширений Joomla для работы с ИИ.

@joomlafeed

Вышли релизы безопасности Joomla 6.0.4 и Joomla 5.4.4

Релиз безопасности Joomla 6.0.4 и Joomla 5.4.4

Проект Joomla! рад сообщить о выходе Joomla 6.0.4 и Joomla 5.4.4. Это релизы безопасности и исправления ошибок для серий 5.x и 6.x.

0 Пользователей и 1 Гость просматривают эту тему.
  • 8 Ответов
  • 6028 Просмотров
*

mpbakunov

  • Захожу иногда
  • 54
  • 1 / 0
Доброго дня!

Был неприятно удивлен когда увидел форму отправки материала со стороны фронт-энд. Практически это тоже самое, что я как админ сайта вижу в бэк-энде. Зачем рядовому автору видеть поля с метатегами, это его  будет путать, отображаются все ссылки ниже редактора текста, которые появились после установки расширений таких как JComments, расширения вставки модуля в статью, отображать ли статью на главной (Это вообще в большенства задач я уверен не автор должен решать) и др. Поэтому вопрос такой, можноли стандартное решение добавления статьи как то настроить чтобы скрыть не нужные поля и поставить некоторым значения по умолчанию (например поле Категория) или нужен стороннее расширение (буду рад услышать варианты). По этой теме прошелся по форуму, но к сожалению так и не нашел ответа который бы меня устроил. Также удивлен что такое чувство что данный стандартный вариант добавления статьи мало кому не подходит. Надеюсь на конкретные советы на мою проблему!

Спасибо
*

BMF

  • Захожу иногда
  • 87
  • 1 / 1
Re: Шаблон отправки материала
« Ответ #1 : 18.08.2010, 09:33:11 »
чтобы удалить поля из формы добавления материалов из фронта (останутся только "название материала", "раздел", "категория" и ниже поле редактора), они не будут видны никому в том числе и суперадмину, идешь в \components\com_content\views\article\tmpl\form.php и заменяешь весь его код на такой
Код
<?php // no direct access
defined('_JEXEC') or die('Restricted access');

$config =& JFactory::getConfig();
$publish_up =& JFactory::getDate($this->article->publish_up);
$publish_up->setOffset($config->getValue('config.offset'));
$publish_up = $publish_up->toFormat();

if (! isset($this->article->publish_down) || $this->article->publish_down == 'Never') {
$publish_down = JText::_('Never');
} else {
$publish_down =& JFactory::getDate($this->article->publish_down);
$publish_down->setOffset($config->getValue('config.offset'));
$publish_down = $publish_down->toFormat();
}
?>

<script language="javascript" type="text/javascript">
<!--
function setgood() {
// TODO: Put setGood back
return true;
}

var sectioncategories = new Array;
<?php
$i = 0;
foreach ($this->lists['sectioncategories'] as $k=>$items) {
foreach ($items as $v) {
echo "sectioncategories[".$i++."] = new Array( '$k','".addslashes( $v->id )."','".addslashes( $v->title )."' );\n\t\t";
}
}
?>

function submitbutton(pressbutton) {
var form = document.adminForm;
if (pressbutton == 'cancel') {
submitform( pressbutton );
return;
}
try {
form.onsubmit();
} catch(e) {
alert(e);
}

// do field validation
var text = <?php echo $this->editor->getContent( 'text' ); ?>
if (form.title.value == '') {
return alert ( "<?php echo JText::_( 'Article must have a title', true ); ?>" );
} else if (text == '') {
return alert ( "<?php echo JText::_( 'Article must have some text', true ); ?>");
} else if (parseInt('<?php echo $this->article->sectionid;?>')) {
// for articles
if (form.catid && getSelectedValue('adminForm','catid') < 1) {
return alert ( "<?php echo JText::_( 'Please select a category', true ); ?>" );
}
}
<?php echo $this->editor->save( 'text' ); ?>
submitform(pressbutton);
}
//-->
</script>
<?php if ($this->params->get('show_page_title', 1)) : ?>
<div class="componentheading<?php echo $this->escape($this->params->get('pageclass_sfx')); ?>"><?php echo $this->escape($this->params->get('page_title')); ?></div>
<?php endif; ?>
<form action="<?php echo $this->action ?>" method="post" name="adminForm" onSubmit="setgood();">
<fieldset>
<legend><?php echo JText::_('Editor'); ?></legend>
<table class="adminform" width="100%">
<tr>
<td>
<div style="float: left;">
<label for="title">
<?php echo JText::_( 'Title' ); ?>:
</label>
<input class="inputbox" type="text" id="title" name="title" size="60" maxlength="100" value="<?php echo $this->escape($this->article->title); ?>" />
<input class="inputbox" type="hidden" id="alias" name="alias" value="<?php echo $this->escape($this->article->alias); ?>" />
</div>
<div style="float: right;">
<button type="button" onclick="submitbutton('save')">
<?php echo JText::_('Save')?>
</button>
<button type="button" onclick="submitbutton('cancel')">
<?php echo JText::_('Cancel')?>
</button>
</div>
</td>
</tr>
</table>
</fieldset>
<fieldset>
<table class="adminform">
<tr >
<td class="key">
<label for="sectionid">
<?php echo JText::_( 'Section' ); ?>:
</label>
</td>
<td>
<?php echo $this->lists['sectionid']; ?>
</td>
</tr>
<tr>
<td class="key">
<label for="catid">
<?php echo JText::_( 'Category' ); ?>:
</label>
</td>
<td>
<?php echo $this->lists['catid']; ?>
</td>
</tr>
</table>
<?php
echo $this->editor->display('text', $this->article->text, '100%', '580', '70', '15');
?>
</fieldset>

<input type="hidden" name="option" value="com_content" />
<input type="hidden" name="id" value="<?php echo $this->article->id; ?>" />
<input type="hidden" name="version" value="<?php echo $this->article->version; ?>" />
<input type="hidden" name="created_by" value="<?php echo $this->article->created_by; ?>" />
<input type="hidden" name="referer" value="<?php echo str_replace(array('"', '<', '>', "'"), '', @$_SERVER['HTTP_REFERER']); ?>" />
<?php echo JHTML::_( 'form.token' ); ?>
<input type="hidden" name="task" value="" />
</form>
<?php echo JHTML::_('behavior.keepalive'); ?>

Если высота поля редактора не устраивает, то ищем строчку
Код
<?php
echo $this->editor->display('text', $this->article->text, '100%', '580', '70', '15');
?>
в ней число '580' и есть высота поля редактора в пикселах (по умолчанию было '400'), можно задать в процентах при желании...
соответственно '100%' - это ширина...
перед этими манипуляциями с файлом form.php СОХРАНИ ОРИГИНАЛ В УКРОМНОМ МЕСТЕ
после этих танцев, при добавлении материалов пользователями с фронта сайта (авторами, админами, суперадминами... всеми) будут видны только "название материала", "раздел", "категория" и поле редактора. Полное редактирование статьи, в частности мета данные, ключевые слова, время начала/конца публикации и тд. будут доступны только из админ панели!
пс. наверно, если использовать шаблон сайта, который будет перекрывать джумловский стандартный, то это все править нужно будет там.
*

maddock

  • Новичок
  • 6
  • 0 / 0
Re: Шаблон отправки материала
« Ответ #2 : 12.01.2011, 22:34:16 »
у меня изменения form.php  не привели не к чему, даже переименование папки tmpl не играет роли,
Но я все таки нашел отвечающий за добавление файл, называется по другому и находится в components\com_content\views\article\view.html.php
вот код
Код
<?php
/**
 * @version $Id: view.html.php 14401 2010-01-26 14:10:00Z louis $
 * @package Joomla
 * @subpackage Content
 * @copyright Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
 * @license GNU/GPL, see LICENSE.php
 * Joomla! is free software. This version may have been modified pursuant to the
 * GNU General Public License, and as distributed it includes or is derivative
 * of works licensed under the GNU General Public License or other free or open
 * source software licenses. See COPYRIGHT.php for copyright notices and
 * details.
 */

// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die( 'Restricted access' );

require_once (JPATH_COMPONENT.DS.'view.php');

/**
 * HTML Article View class for the Content component
 *
 * @package Joomla
 * @subpackage Content
 * @since 1.5
 */
class ContentViewArticle extends ContentView
{
function display($tpl = null)
{
global $mainframe;

$user =& JFactory::getUser();
$document =& JFactory::getDocument();
$dispatcher =& JDispatcher::getInstance();
$pathway =& $mainframe->getPathway();
$params =& $mainframe->getParams('com_content');

// Initialize variables
$article =& $this->get('Article');
$aparams =& $article->parameters;
$params->merge($aparams);

if($this->getLayout() == 'pagebreak') {
$this->_displayPagebreak($tpl);
return;
}

if($this->getLayout() == 'form') {
$this->_displayForm($tpl);
return;
}

if (($article->id == 0))
{
$id = JRequest::getVar( 'id', '', 'default', 'int' );
return JError::raiseError( 404, JText::sprintf( 'Article # not found', $id ) );
}

$limitstart = JRequest::getVar('limitstart', 0, '', 'int');

if (!$params->get('intro_only') && ($this->getLayout() == 'default') && ($limitstart == 0))
{
$model =& $this->getModel();
$model->hit();
}

// Create a user access object for the current user
$access = new stdClass();
$access->canEdit = $user->authorize('com_content', 'edit', 'content', 'all');
$access->canEditOwn = $user->authorize('com_content', 'edit', 'content', 'own');
$access->canPublish = $user->authorize('com_content', 'publish', 'content', 'all');

// Check to see if the user has access to view the full article
$aid = $user->get('aid');

if ($article->access <= $aid) {
$article->readmore_link = JRoute::_(ContentHelperRoute::getArticleRoute($article->slug, $article->catslug, $article->sectionid));;
} else {
if ( ! $aid )
{
// Redirect to login
$uri = JFactory::getURI();
$return = $uri->toString();

$url  = 'index.php?option=com_user&view=login';
$url .= '&return='.base64_encode($return);;

//$url = JRoute::_($url, false);
$mainframe->redirect($url, JText::_('You must login first') );
}
else{
JError::raiseWarning( 403, JText::_('ALERTNOTAUTH') );
return;
}
}

/*
* Process the prepare content plugins
*/
JPluginHelper::importPlugin('content');
$results = $dispatcher->trigger('onPrepareContent', array (& $article, & $params, $limitstart));

/*
* Handle the metadata
*/
// because the application sets a default page title, we need to get it
// right from the menu item itself
// Get the menu item object
$menus = &JSite::getMenu();
$menu  = $menus->getActive();

if (is_object( $menu ) && isset($menu->query['view']) && $menu->query['view'] == 'article' && isset($menu->query['id']) && $menu->query['id'] == $article->id) {
$menu_params = new JParameter( $menu->params );
if (!$menu_params->get( 'page_title')) {
$params->set('page_title', $article->title);
}
} else {
$params->set('page_title', $article->title);
}
$document->setTitle( $params->get( 'page_title' ) );

if ($article->metadesc) {
$document->setDescription( $article->metadesc );
}
if ($article->metakey) {
$document->setMetadata('keywords', $article->metakey);
}

if ($mainframe->getCfg('MetaTitle') == '1') {
$mainframe->addMetaTag('title', $article->title);
}
if ($mainframe->getCfg('MetaAuthor') == '1') {
$mainframe->addMetaTag('author', $article->author);
}

$mdata = new JParameter($article->metadata);
$mdata = $mdata->toArray();
foreach ($mdata as $k => $v)
{
if ($v) {
$document->setMetadata($k, $v);
}
}

// If there is a pagebreak heading or title, add it to the page title
if (!empty($article->page_title))
{
$article->title = $article->title .' - '. $article->page_title;
$document->setTitle($article->page_title.' - '.JText::sprintf('Page %s', $limitstart + 1));
}

/*
* Handle the breadcrumbs
*/
if($menu && $menu->query['view'] != 'article')
{
switch ($menu->query['view'])
{
case 'section':
$pathway->addItem($article->category, 'index.php?view=category&id='.$article->catslug);
$pathway->addItem($article->title, '');
break;
case 'category':
$pathway->addItem($article->title, '');
break;
}
}

/*
* Handle display events
*/
$article->event = new stdClass();
$results = $dispatcher->trigger('onAfterDisplayTitle', array (&$article, &$params, $limitstart));
$article->event->afterDisplayTitle = trim(implode("\n", $results));

$results = $dispatcher->trigger('onBeforeDisplayContent', array (&$article, &$params, $limitstart));
$article->event->beforeDisplayContent = trim(implode("\n", $results));

$results = $dispatcher->trigger('onAfterDisplayContent', array (&$article, &$params, $limitstart));
$article->event->afterDisplayContent = trim(implode("\n", $results));

$print = JRequest::getBool('print');
if ($print) {
$document->setMetaData('robots', 'noindex, nofollow');
}

$this->assignRef('article', $article);
$this->assignRef('params' , $params);
$this->assignRef('user'   , $user);
$this->assignRef('access' , $access);
$this->assignRef('print', $print);

parent::display($tpl);
}

function _displayForm($tpl)
{
global $mainframe;

// Initialize variables
$document =& JFactory::getDocument();
$user =& JFactory::getUser();
$uri =& JFactory::getURI();
$params =& $mainframe->getParams('com_content');

// Make sure you are logged in and have the necessary access rights
if ($user->get('gid') < 19) {
JResponse::setHeader('HTTP/1.0 403',true);
  JError::raiseWarning( 403, JText::_('ALERTNOTAUTH') );
return;
}

// Initialize variables
$article =& $this->get('Article');
$aparams =& $article->parameters;
$isNew = ($article->id < 1);

$params->merge($aparams);

// At some point in the future this will come from a request object
$limitstart = JRequest::getVar('limitstart', 0, '', 'int');

// Add the Calendar includes to the document <head> section
JHTML::_('behavior.calendar');

if ($isNew)
{
// TODO: Do we allow non-sectioned articles from the frontend??
$article->sectionid = JRequest::getVar('sectionid', 0, '', 'int');
$db = JFactory::getDBO();
$db->setQuery('SELECT title FROM #__sections WHERE id = '.(int) $article->sectionid);
$article->section = $db->loadResult();
}

// Get the lists
$lists = $this->_buildEditLists();

// Load the JEditor object
$editor =& JFactory::getEditor();

// Build the page title string
$title = $article->id ? JText::_('Edit') : JText::_('New');

// Set page title
// because the application sets a default page title, we need to get it
// right from the menu item itself
// Get the menu item object
$menus = &JSite::getMenu();
$menu  = $menus->getActive();
$params->set( 'page_title', $params->get( 'page_title' ) );
if (is_object( $menu )) {
$menu_params = new JParameter( $menu->params );
if (!$menu_params->get( 'page_title')) {
$params->set('page_title', JText::_( 'Submit an Article' ));
}
} else {
$params->set('page_title', JText::_( 'Submit an Article' ));
}
$document->setTitle( $params->get( 'page_title' ) );

// get pathway
$pathway =& $mainframe->getPathWay();
$pathway->addItem($title, '');

// Unify the introtext and fulltext fields and separated the fields by the {readmore} tag
if (JString::strlen($article->fulltext) > 1) {
$article->text = $article->introtext."<hr id=\"system-readmore\" />".$article->fulltext;
} else {
$article->text = $article->introtext;
}

$this->assign('action', $uri->toString());

$this->assignRef('article', $article);
$this->assignRef('params', $params);
$this->assignRef('lists', $lists);
$this->assignRef('editor', $editor);
$this->assignRef('user', $user);


parent::display($tpl);
}

function _buildEditLists()
{
// Get the article and database connector from the model
$article = & $this->get('Article');
$db = & JFactory::getDBO();

$javascript = "onchange=\"changeDynaList( 'catid', sectioncategories, document.adminForm.sectionid.options[document.adminForm.sectionid.selectedIndex].value, 0, 0);\"";

$query = 'SELECT s.id, s.title' .
' FROM #__sections AS s' .
' ORDER BY s.ordering';
$db->setQuery($query);

$sections[] = JHTML::_('select.option', '-1', '- '.JText::_('Select Section').' -', 'id', 'title');
$sections[] = JHTML::_('select.option', '0', JText::_('Uncategorized'), 'id', 'title');
$sections = array_merge($sections, $db->loadObjectList());
$lists['sectionid'] = JHTML::_('select.genericlist',  $sections, 'sectionid', 'class="inputbox" size="1" '.$javascript, 'id', 'title', intval($article->sectionid));

foreach ($sections as $section)
{
$section_list[] = (int) $section->id;
// get the type name - which is a special category
if ($article->sectionid) {
if ($section->id == $article->sectionid) {
$contentSection = $section->title;
}
} else {
if ($section->id == $article->sectionid) {
$contentSection = $section->title;
}
}
}

$sectioncategories = array ();
$sectioncategories[-1] = array ();
$sectioncategories[-1][] = JHTML::_('select.option', '-1', JText::_( 'Select Category' ), 'id', 'title');
$section_list = implode('\', \'', $section_list);

$query = 'SELECT id, title, section' .
' FROM #__categories' .
' WHERE section IN ( \''.$section_list.'\' )' .
' ORDER BY ordering';
$db->setQuery($query);
$cat_list = $db->loadObjectList();

// Uncategorized category mapped to uncategorized section
$uncat = new stdClass();
$uncat->id = 0;
$uncat->title = JText::_('Uncategorized');
$uncat->section = 0;
$cat_list[] = $uncat;
foreach ($sections as $section)
{
$sectioncategories[$section->id] = array ();
$rows2 = array ();
foreach ($cat_list as $cat)
{
if ($cat->section == $section->id) {
$rows2[] = $cat;
}
}
foreach ($rows2 as $row2) {
$sectioncategories[$section->id][] = JHTML::_('select.option', $row2->id, $row2->title, 'id', 'title');
}
}

$categories = array();
foreach ($cat_list as $cat) {
if($cat->section == $article->sectionid)
$categories[] = $cat;
}

$categories[] = JHTML::_('select.option', '-1', JText::_( 'Select Category' ), 'id', 'title');
$lists['sectioncategories'] = $sectioncategories;
$lists['catid'] = JHTML::_('select.genericlist',  $categories, 'catid', 'class="inputbox" size="1"', 'id', 'title', intval($article->catid));

// Select List: Category Ordering
$query = 'SELECT ordering AS value, title AS text FROM #__content WHERE catid = '.(int) $article->catid.' AND state > ' .(int) "-1" . ' ORDER BY ordering';
$lists['ordering'] = JHTML::_('list.specificordering', $article, $article->id, $query, 1);

// Radio Buttons: Should the article be published
$lists['state'] = JHTML::_('select.booleanlist', 'state', '', $article->state);

// Radio Buttons: Should the article be added to the frontpage
if($article->id) {
$query = 'SELECT content_id FROM #__content_frontpage WHERE content_id = '. (int) $article->id;
$db->setQuery($query);
$article->frontpage = $db->loadResult();
} else {
$article->frontpage = 0;
}

$lists['frontpage'] = JHTML::_('select.booleanlist', 'frontpage', '', (boolean) $article->frontpage);

// Select List: Group Access
$lists['access'] = JHTML::_('list.accesslevel', $article);

return $lists;
}

function _displayPagebreak($tpl)
{
$document =& JFactory::getDocument();
$document->setTitle(JText::_('PGB ARTICLE PAGEBRK'));

parent::display($tpl);
}
}

как его отредактировать чтоб были только заголовок, материал, а категория выставлялась по умолчанию только одна, не был предложен список.
*

maddock

  • Новичок
  • 6
  • 0 / 0
Re: Шаблон отправки материала
« Ответ #3 : 12.01.2011, 23:16:48 »
Все разобрался  ^-^ . Оказывается действительно шаблоновский файл перекрывал.
*

maddock

  • Новичок
  • 6
  • 0 / 0
Re: Шаблон отправки материала
« Ответ #4 : 13.01.2011, 09:20:36 »
Вот только один вопрос остался нерешенным, как изменить код чтоб пользователю не давался выбор категории, надо чтобы по умолчанию материал отправлялся  в определенный раздел и категорию?
*

yoralbayev

  • Новичок
  • 2
  • 0 / 0
Re: Шаблон отправки материала
« Ответ #5 : 31.07.2011, 21:58:43 »
Я вот эту компонент использую в двух местах. и проблема состоит в том что в одном пользовался зарегистрированное пользователей а втором только администраторы и модераторы. В первом случай покозался только один раздел а втором все.  За ране благодарю.
*

mister73rus

  • Новичок
  • 8
  • 1 / 0
Re: Шаблон отправки материала
« Ответ #6 : 28.12.2011, 05:31:30 »
я так понял тут обсуждалось про версию 1.5 , кто знает как всё же убрать при добавлении материала в 1.7 вот такие ненужные для пользователя поля: Алиас, Псевдоним автора, Доступ, Язык, Метаданные Мета-тег Description, Мета-тег Keywords
*

mdghouse

  • Осваиваюсь на форуме
  • 31
  • 0 / 0
Re: Шаблон отправки материала
« Ответ #7 : 27.10.2013, 20:07:23 »
Что самое интересное, что уже столько лет Joomla, а я так и не видел какого-либо модуля или компонента заменяющего стандартную форму добавления материалов.
*

AlexJoomla

  • Осваиваюсь на форуме
  • 49
  • 1 / 3
Re: Шаблон отправки материала
« Ответ #8 : 03.11.2013, 11:51:19 »
Что самое интересное, что уже столько лет Joomla, а я так и не видел какого-либо модуля или компонента заменяющего стандартную форму добавления материалов.

Это точно! Но может всё же есть, может люди знающие подскажут?
Чтобы оставить сообщение,
Вам необходимо Войти или Зарегистрироваться
 

Форма отправки! HELP me please

Автор annetkas

Ответов: 1
Просмотров: 3654
Последний ответ 03.02.2022, 19:05:09
от annetkas
AcyMailing вместо отправки письма открывает страницу с GitHub

Автор Podryvnik

Ответов: 8
Просмотров: 2053
Последний ответ 23.06.2020, 13:20:56
от Podryvnik
Шаблон «Протостар»: форма обратной связи

Автор ilya-larin

Ответов: 2
Просмотров: 1183
Последний ответ 06.08.2019, 08:11:49
от ilya-larin
Как можно найти такой шаблон?

Автор YuliaOks

Ответов: 6
Просмотров: 1512
Последний ответ 04.06.2019, 04:21:22
от Missile
Проблема с временем pm/am в компоненте sp soccer (шаблон shaper soccer)

Автор Mira

Ответов: 7
Просмотров: 1859
Последний ответ 21.04.2019, 13:52:42
от Mira