Joomla для разработчиков
103 subscribers
15 photos
62 links
Полезное из мира Joomla:
- документация для разработчиков и опытных пользователей;
- интересные находки.

Мы ВКонтакте - https://vk.com/jpathru
Наш веб-сайт - https://jpath.ru

Есть интересный материал? @drekun
Download Telegram
Как и для чего использовать Dependency Injection Containers в Joomla

Потихоньку перетаскиваем материалы с Хабра к себе 😊

Спасибо С.Толкачёву за первоначальную публикацию 🤝

https://jpath.ru/docs/basics/dependency-injection-containers
🔥2👍1
Forwarded from WebTolkRu (Sergey Tolkachyov)
Layouts и subLayouts в Joomla
В Joomla есть понятие layout. Это кусочек вёрстки, который можно многажды использовать в любом месте сайта: как в панели администратора, так и во фронтенде. Можно рассматривать лейауты как оторванные от контекста элементы дизайна. Находятся они в папке layouts в корне сайта. Как их использовать? Один из вариантов - использование LayoutHelper.
use Joomla\CMS\Layout\LayoutHelper;

// $item - ваш объект или массив с данными, которые нужно использовать в верстке

echo LayoutHelper::render('components.swjprojects.project.icons', ['item' => $item]);

1-й аргумент - это dot-separated (разделенный точками) путь к файлу лейаута. Название папки
"layouts" в данном случае пропускается как само собой разумеющееся. На скриншоте путь отмечен цифрами 1-4. Внутрь файла приходит массив $displayData, в котором будет лежать наш $item - $displayData['item'].
extract($displayData);

echo '<button role="button" class="btn btn-primary">'.$item->title.'</button>';

Либо же, если макет можно раздробить на более мелкие примитивы - тулбар с иконками разбить на отдельные иконки - то можно использовать метод subLayout().
В первом примере кода мы "вошли" в лейаут icons. А в файле icons.php можно вызвать подмакеты. Для этого нужно создать рядом папку с таким же названием - icons. А в нём уже будут лежать файлы подмакетов.
// icons.php
extract($displayData);

// обращаемся к /icons/downloads.php
echo $this->sublayout('downloads', $displayData);

// обращаемся к /icons/hits.php
echo $this->sublayout('hits', $displayData);

Передавать туда можно как целиком $displayData, так и какую-то часть от него. Тут уже как вам удобно.

Также помним, что файлы из layouts подвержены переопределениями в шаблонах.

Где это применимо? Да в принципе везде, хотя данный пример относится к разработке компонента.

@webtolkru

#joomla #development #php #разработка
🔥5
Forwarded from Joomla Feed (Sergey Tolkachyov)
Как добавить свой таб или поле в интерфейс Joomla с помощью плагина. «Joomla way».
Задачи могут быть самые разные: поле аватара для пользователя в com_users, дополнительный таб в форму редактирования материала, поле связи одной сущности с другой и т.д. Сразу оговорюсь, что бывает и "non-Joomla way" - то есть подходы, которые не предполагаются ядром CMS, но при этом и явно не запрещаются. Сейчас речь пойдёт о традиционном пути, который состоит из 2-х простых шагов.

Читать на Хабре

#joomla #php #разработка
👍3
Forwarded from Joomla Feed (Sergey Tolkachyov)
Как добавить свой повторяемый элемент интерфейса в класс HTMLHelper Joomla 4+
В API Joomla есть полезный инструмент - класс HTMLHelper. Он выводит HTML-элементы интерфейса с нужными параметрами: модальные окна, аккордеоны, табы, изображения и т.д. Для рендера мы передаём все нужные данные: заголовки окон, содержимое табов, атрибуты изображений.

Плюс использования HTMLHelper в Joomla - это его универсальность, оторванность от контекста, возможность использования логики при рендере в зависимости от вводных данных, его можно использовать везде. Но что если нам нужно создать свой собственный класс?..

Читать статью на Хабре

#разработка #php #joomla #development
👍3
Forwarded from Joomla Feed (Sergey Tolkachyov)
Подготовка расширений к Joomla 6: CMSObject -> stdClass
В Joomla 6 метод getItem() в Adminmodel будет возвращать \stdClass вместо CMSObject. Это означает, что все устаревшие функции этого класса будут недоступны. Разработчики в Joomla 6 должны напрямую работать со свойствами объекта item и не использовать устаревшие методы set() и get().
Устаревший способ
$article = $app->bootComponent('content')->getMVCFactory()->createModel('Article', 'Administrator')->getItem(1);
echo $article->get('title');

Как будет в Joomla 6
$article = $app->bootComponent('content')->getMVCFactory()->createModel('Article', 'Administrator')->getItem(1);
echo $article->title;

Соответствующий Pull Request уже принят в ветку Joomla 6.

PR на GitHub


#php #joomla #разработка #development #webdev
👍3
Forwarded from Joomla Feed (Sergey Tolkachyov)
Триггеры ядра Joomla при CRUD-операциях

CRUD - аббревиатура основных операций с данными: создание (Create), чтение (Read), изменение (Update) и удаление (Delete). Практически все действия на сайте как в админке, так и пользовательской части можно описать этими действиями. Разработчикам при создании функционала часто в какие-то моменты этих действий нужно проделать некие действия с участием данных или без них.

Как найти нужное событие для своего плагина в Joomla подскажет эта статья.

Читать статью на Хабре

@joomlafeed

#разработка #php #development
👍2
Forwarded from WebTolkRu (Sergey Tolkachyov)
E-mail шаблоны Joomla 5: добавление и просмотр своих переменных
В Joomla 5 появились настраиваемые email-шаблоны, как системные, так и сторонних компонентов. Их нельзя (пока что) добавить самостоятельно, они добавляются расширениями при установке. Но их можно отредактировать в Система - Шаблоны - Шаблоны писем. В настройках шаблонов писем (кнопка настроек компонента в верхнем правом углу) мы выбираем формат писем текст или HTML. Тогда становятся доступны настройки макетов шаблонов писем Joomla. Эти глобальные параметры можно переопределить в каждом конкретном email-шаблоне. Таким образом для каждого из email-шаблонов можно указать свою вёрстку и настройки логотипа.
Это, конечно, требует отдельной подробной статьи...

Для разработчиков: как добавить свои переменные для e-mail шаблонов Joomla?
Полезны окажутся 2 триггера для плагинов: onMailBeforeTagsRendering и onMailBeforeRendering.
onMailBeforeRendering - триггер, который позволяет добавлять свои шорт-коды для строковой замены в плагине. Отдать туда надо массив вида [ variable_name => variable_value ]. Из админки свои переменные нужно добавлять уже с фигурными скобками: {variable_name} заменится на variable_value. Аргументом $event плагина является экземпляр класса BeforeRenderingMailTemplateEvent, в котором есть кроме прочих 2 метода: getTemplate() (получение объекта мейлера, куда можно добавлять свои данные) и getTemplateId() (получение id шаблона письма вида com_users.registration.admin.new_notification), по которому мы определяем нужный ли это для нас email-шаблон или нет. Аналогично контексту в контент-плагинах.
Также полезное свойство класса для передачи данных из плагина в лейаут письма для рендера - $layoutTemplateData. Это ассоциативный массив.

```php
// Получаем текущий мейлер
$mailTemplate = $event->getTemplate();
$data = [
'variable_name' => 'variable_value'
];
// с Joomla 4 для всех типов писем. 2-й аргумент - plain - текстовый формат письма
$mailTemplate->addTemplateData($data, false);
// с Joomla 5.2 - для HTML-писем
$mailTemplate->addLayoutTemplateData($data);

// пример из ядра Joomla
// Add additional data to the layout template
$this->addLayoutTemplateData([
'siteName' => $app->get('sitename'),
'lang' => substr($this->language, 0, 2),
]);
```
onMailBeforeTagsRendering - триггер, который добавляет ваши переменные в список доступных переменных для замены в окне редактирования email шаблона Joomla. Отдать туда нужно тот же самый массив, который отдавали в предыдущем триггере.

@webtolkru

#joomla #разработка #php #development #webdev
Forwarded from Joomla Feed (Sergey Tolkachyov)
Добавляем свои переменные в шаблоны писем Joomla 5+

Это полноценная статья о создании плагина, который добавляет переменные-шорткоды для обработки в email-шаблонах Joomla. Кроме того, рассказывается и о том, как в качестве значений для шорт кодов использовать данные пользовательских полей com_users.

Статья написана участником нашего сообщества Александром Новиковым (@pro_portal).

Читать статью

Это творческий дебют автора, поэтому давайте поддержим его плюсами в карму 👩‍💻.

Плагин, о котором идёт речь в статье

joomLab MailAuthor: почтовые уведомления авторам материалов об изменении статуса публикации
Этот плагин позволит Вам реализовать функционал отправки почтового (e-mail) уведомления авторам материалов о статусе публикации их статей. При опубликовании материала или снятия с публикации, автор материала получит уведомление на почту.

Страница расширения
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Forwarded from Joomla Feed (Sergey Tolkachyov)
Joomla Web Services Collection For Postman

Разработчикам мобильных и WEB-приложений (и не только) весьма и весьма пригодится готовая коллекция для Postman. В коллекцию добавлены endpoint для REST API Joomla, с параметрами и примерами запросов.

Коллекция составлена трудами французского Joomla-разработчика Alexandre J-S William ELISÉ.

Смотреть коллекцию

@jooomlafeed

#joomla #restapi #webdev #разработка
Forwarded from WebTolkRu (Sergey Tolkachyov)
Joomla-разработчикам: обращение к методам модели в HtmlView напрямую

Когда-то, давным-давно в одной далёкой галактике кто-то решил, что что было бы неплохой идеей ввести косвенный доступ к методам модели (MVC) для получения данных, добавив метод AbstractView::get(). Этот метод извлекает модель и затем запускает get<Parameter>(). Простыми словами, когда мы во View (файл HtmlView нашего компонента) видим конструкцию $this->item = $this->get('Item') это означает обращение к методу getItem() модели для текущего View.

Но такой подход исключает любую возможность подсказки типов, аргументов и т. д. и делает все излишне сложным. Поэтому разработчики ядра Joomla объявили этот метод устаревшим с этим PR 44162.
Новый способ выглядит так:
// Файл HtmlView компонента

public function display($tpl = null)
{
$model = $this->getModel();
$this->items = $model->getItems();

parent::display($tpl);
}

Старый подход (то есть метод get() во View) будет удалён в Joomla 7. Памятуя о релизном цикле Joomla, это означает, что:
1️⃣ осенью 2025г выйдет Joomla 6.
2️⃣ 2 года она будет основной веткой. Joomla 5 будет в режиме поддержки
3️⃣ через 2 года, в 2027 выйдет Joomla 7, в которой будет удалён этот метод.
4️⃣ но Joomla 6 будет ещё 2 года в режиме тех.поддержки и в ней (до 2029 года) этот метод останется.

Таким образом у разработчиков есть от 2,5 до 4,5 лет (на момент написания этого поста) на то, чтобы сделать этот рефакторинг.

👩‍💻👩‍💻 [5.3] Deprecate AbstractView::get() #44162

@webtolkru

#joomla #разработка #php #webdev
👍1
Forwarded from Joomla Feed (Sergey Tolkachyov)
👩‍💻 Совет по Joomla: $db->getQuery(true) стал устаревшим.
Раньше при создании запросов в базу данных мы всегда получали объект запроса с помощью метода getQuery(). Если передавался параметр $new = true, то получали новый запрос. Если без - последний.
use Joomla\CMS\Factory;

$db = Factory::getContainer()->get('DatabaseDriver');

$query = $db->getQuery(new: true);
// и строим запрос

Под капот Joomla 4 вошёл Joomla Framework (PHP фреймворк а-ля Laravel, Yii и т.д.), а для Joomla 5 он обновился - версия 3.4.1 вышла 6 октября 2023г. В методе фреймворка есть примечание о том, что параметр $new, который передавался в метод getQuery() помечен как устаревший и будет удалён в версии фреймворка 4.0.
The parameter $new is deprecated and will be removed in 4.0, use %s::createQuery() instead.

В Joomla 4 версия Joomla Framework была 2.x., в Joomla 5 - 3.x. Поэтому есть предположение, что с выходом Joomla 6 обновится и версия фреймворка - станет 4.0.
Поэтому для получения объекта для новых запросов следует использовать метод createQuery(). Он уже представлен в ядре и широко используется. При этом метод getQuery() останется, но, скорее всего, будет выполнять функцию только геттера - получения текущего запроса.

@joomlafeed

#joomla #php #разработка
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Forwarded from Joomla Feed (Sergey Tolkachyov)
Новый способ добавления и рендера полей в Joomla Form - метод renderControlFields() (Joomla 5.3+).
При отображении форм компонента в админке раньше разработчикам нужно было описывать скрытые поля в лейаутах. И выглядело это так:
<?php
// Это файл в /layouts/components/com_component/your_layout.php
?>
<input type="hidden" name="task" value="">
<input type="hidden" name="return" value="<?php echo $input->getBase64('return'); ?>">
<input type="hidden" name="forcedLanguage" value="<?php echo $input->get('forcedLanguage', '', 'cmd'); ?>">
<?php echo HTMLHelper::_('form.token'); ?>

Начиная с Joomla 5.3 добавлен новый способ добавления таких полей (их называют control fields) - программно. И теперь это можно сделать просто в Controller / View.
// В Controller/View добавляем поля
$this->form
->addControlField('task', '')
->addControlField('return', $input->getBase64('return', ''))
->addControlField('forcedLanguage', $forcedLanguage);

А в layout'е просто используем метод renderControlFields()
// В layout формы
echo $this->form->renderControlFields();

Многие компоненты ядра уже используют этот подход. Соответствующий PR был принят в Joomla 5.3 осенью 2024г.

Смотреть Pull Request

@joomlafeed

#joomla #разработка #php
А вы ставите в PHP перед вызовом функций обратный слэш
https://habr.com/ru/articles/934316/
Anonymous Poll
23%
Да
54%
Нет
23%
Как когда...
Какой интерфейс нужно реализовать, чтобы создать пользовательский плагин с собственными обработчиками событий?
Anonymous Quiz
18%
EventInterface
18%
DispatcherInterface
64%
EventSubscriberInterface
Как в Joomla 5 получить активный пункт меню?
Anonymous Quiz
17%
Factory::getMenu()->getActive()
72%
Factory::getApplication()->getMenu()->getActive()
11%
MenuHelper::active()
Как получить текущего пользователя в Joomla 5?
Anonymous Quiz
35%
Factory::getApplication()->getUser()
18%
Factory::getUser()
47%
Factory::getApplication()->getIdentity()
Какой константой можно получить текущую версию Joomla?
Anonymous Quiz
67%
JVERSION
17%
JOOMLA_VERSION
17%
CMS_VERSION
Forwarded from WebTolkRu (Sergey Tolkachyov)
👩‍💻 Свои типы полей в Joomla.
Это большая тема, о которой можно говорить очень много. Самое главное, что возможности применения ограничиваются только вашей больной фантазией. Вы строите интерфейс своего модуля или плагина и вам нужно подтянуть данные из сторонней системы (список чего-нибудь по какому-нибудь API), чтобы сохранить выбранный id в Joomla. Или сделать какую-то проверку и в зависимости от неё показать то или иное сообщение пользователю. Для этого подойдут свои пользовательские типы полей.

Интерфейс Joomla по большей части описан в XML-файлах. У каждого из них свои параметры. Некоторые не описаны в документации (manual.joomla.org), поэтому самым любопытным будет полезно заглянуть в собственно файлы фреймворка по пути libraries/src/Form/FormField.php, а так же в libraries/src/Form/Fields. У каждого класса поля перечислены его специфические свойства, которые можно описывать в XML. А в своём типе поля вы можете устанавливать эти значения программно.

В моём модуле WT Quick links под капотом происходят изменения. Теперь для работы (в админке) ему нужен вспомогательный плагин. А в самом модуле нам бы проверить, а не выключен ли он?

В Joomla есть тип поля Note - заметка. Его можно использовать для вывода примечаний.
<field type="note"
name="your_note_for_user"
label="Заголовок примечания"
title="Альтернативный способ для заголовка"
description="Текст примечания"
class="col-12 alert alert-info"
heading="h1"
close="true"
/>

heading - указывать уровень заголовка. close - позволяет закрыть это примечание.

В классе поля libraries/src/Form/Field/NoteField.php описана логика вывода. И в принципе оно нам подходит для нашей задачи. Но оно будет выводить сообщение всегда, а нам нужно только тогда, когда плагин отключён.

Поэтому берём и создаём свой класс поля, который мы унаследуем от NoteField. Это значит, что у нас в руках будет весь инструментарий стандартного поля Note + то, что мы сами добавим.

В XML-манифест добавляем наше поле
<field type="systempluginstatus" 
name="systempluginstatus"
addfieldprefix="Joomla\Module\Wtquicklinks\Site\Fields"/>

- type - имя файла и класса,
- addfieldprefix - указываем namespace к нашему классу, может быть любой нам нужный
- name - нельзя полю без имени...
Это означает, что Joomla будет использовать класс поля из файла modules/mod_wt_quick_links/src/Fields/SystempluginstatusField.php.
А в классе поля будет написано следующее:
<?php
// namespace для атрибута addfieldprefix
namespace Joomla\Module\Wtquicklinks\Site\Fields;
// нельзя напрямую обращаться к этому файлу
defined('_JEXEC') or die;
// подключаем родительский класс для переопределения
use Joomla\CMS\Form\Field\NoteField;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;

// имя класса и имя файла точь-в-точь
class SystempluginstatusField extends NoteField
{
protected $type = 'Systempluginstatus';

protected function getLabel()
{
// если плагин не включён
if(PluginHelper::isEnabled('system','wtquicklinks')) {
// меняем свойства родительского класса
$this->class = 'alert alert-danger w-100';
$this->element['label'] = '⚠️ А-а-а-а!';
$this->element['description'] = 'Плагин не включён!!';
// и просто рендерим его с нашими свойствами
return parent::getLabel();
}
// А иначе всё хорошо, скрываем поле из виду.
$this->parentclass = 'd-none';
return '';
}
}

Просто и удобно. И людям приятно, что о них позаботились и рассказали почему что-то не работает.

@webtolkru

#joomla #php #webdev #разработка
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Forwarded from Joomla Feed (Sergey Tolkachyov)
👩‍💻 Как триггерить события для плагинов на манер Joomla 5+?
В Joomla 6 должны удалить метод triggerEvent(), с помощью которого раньше вызывались события для плагинов. Теперь чтобы в своём коде вызвать событие для плагина и получить от него результаты нужно:
- создать объект класса события
- передать в него параметры
use Joomla\CMS\Event\AbstractEvent;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;

// Грузим плагины нужных групп
PluginHelper::importPlugin('system');
// Создаём объект события
$event = AbstractEvent::create('onAfterInitUniverse', [
'subject' => $this,
'data' => $data, // какие-то данные
'article' => $article, // ещё материал вдовесок
'product' => $product, // и товаров подвезли
]);
// Триггерим событие
Factory::getApplication()->getDispatcher()->dispatch(
$event->getName(), // Тут можно строку передать 'onAfterInitUniverse'
$event
);
// Получаем результаты
// В случае с AbstractEvent это может быть не 'result',
// а что-то ещё - куда сами отдадите данные.
// 2-й аргумент - значение по умолчанию,
// если не получены результаты
$results = $event->getArgument('result', []);

Плюсы такого подхода - вам не нужно запоминать порядок аргументов и проверять их наличие. Если вы написали свой класс события, то в плагине можно получать аргументы с помощью методов $event->getArticle(), $event->getData(), $event->getProduct() и подобными - реализуете сами под свои нужды.
Если такой класс события написали, то создаёте экземпляр своего класса события и укажите его явно в аргументе eventClass
use Joomla\Component\MyComponent\Administrator\Event\MyCoolEvent;

$event = MyCoolEvent::create('onAfterInitUniverse', [
'subject' => $this,
'eventClass' => MyCoolEvent::class, // ваш класс события
'data' => $data, // какие-то данные
'article' => $article, // ещё материал вдовесок
'product' => $product, // и товаров подвезли
]);

Ожидаемо, что класс вашего события будет расширять AbsractEvent или другие классы событий Joomla.

🙁 Есть неприятный нюанс - нельзя просто так вызывать событие и ничего не передать в аргументы. Аргумент subject обязательный. Но если вы всё-таки не хотите туда ничего передавать - передайте туда пустой stdClass или объект Joomla\registry\Registry.

@joomlafeed

#joomla #php #webdev
Please open Telegram to view this post
VIEW IN TELEGRAM