<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sergey Tolkachyov</title>
    <description>The latest articles on DEV Community by Sergey Tolkachyov (@sergeytolkachyov).</description>
    <link>https://dev.to/sergeytolkachyov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1313911%2F1ea781c7-dc69-467c-988a-32aadc3cd2df.jpeg</url>
      <title>DEV Community: Sergey Tolkachyov</title>
      <link>https://dev.to/sergeytolkachyov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sergeytolkachyov"/>
    <language>en</language>
    <item>
      <title>CFI Plugin v.2.0.0 Released - Export/Import Joomla Articles to/from CSV</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Mon, 19 Jan 2026 09:44:59 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/cfi-plugin-v200-released-exportimport-joomla-articles-tofrom-csv-35d8</link>
      <guid>https://dev.to/sergeytolkachyov/cfi-plugin-v200-released-exportimport-joomla-articles-tofrom-csv-35d8</guid>
      <description>&lt;p&gt;This plugin allows you to export Joomla articles to a CSV file. You can then edit the data in a spreadsheet editor (e.g., Excel or Open Office Calc) and upload the file back. In some cases, this is more convenient and faster. The plugin allows exporting tag IDs, working with custom article fields in Joomla, as well as usually non-editable article properties like hits, modification date, etc.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Initial versions of the CFI plugin were created by developer AlekVolsk for Joomline. He created versions 1.0.0-1.0.16 for Joomla 3. Subsequently, in 2026, the plugin was transferred to WebTolk for further development.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  v.2.0.0. What's New?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring.&lt;/strong&gt; The plugin has been completely rewritten from scratch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New Import/Export Interface.&lt;/strong&gt; Export and import now open in a modal window. Functionality to select article properties, tags, and custom fields for export right before the export itself has been added.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Article Filtering During Export.&lt;/strong&gt; You can filter the articles you need using standard search parameters in the admin panel, and then export only those: only featured ones, only published ones, only articles from 2 categories, only articles with a specific tag, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import/Export All Article Data.&lt;/strong&gt; Previously, the plugin could only export some article data. Now, during export and import, you can change all article data found in the article editing form, even non-editable ones like hits or modification date. This way, you can quickly update all meta-descriptions or just the field data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import Custom Fields Only.&lt;/strong&gt; The &lt;code&gt;articleid&lt;/code&gt; field remains mandatory for import. Thus, you can import only custom field data without changing the article data itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Joomla 6.&lt;/strong&gt; The plugin has been rewritten with the current structure for Joomla 4+ and successfully tested on Joomla 6.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For Developers: Pre-processing by Plugins.&lt;/strong&gt; You can process data with your own plugins of the &lt;code&gt;cfi&lt;/code&gt; group on-the-fly, directly before importing or exporting data. Events: &lt;code&gt;onExportPrepareData($event)&lt;/code&gt; and &lt;code&gt;onImportPrepareArticleData($event)&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;System Requirements:&lt;/strong&gt; Joomla 4.3+, PHP 8.1+.&lt;/p&gt;

&lt;p&gt;To update from older versions, release 1.0.16 is available, which adds a new update server.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extension Page (&lt;a href="https://web-tolk.ru/dev/joomla-plugins/cfi-eksport-import-materialov-joomla?utm_source=dev.to"&gt;https://web-tolk.ru/dev/joomla-plugins/cfi-eksport-import-materialov-joomla?utm_source=dev.to&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Extension GitHub (&lt;a href="https://github.com/WebTolk/cfi" rel="noopener noreferrer"&gt;https://github.com/WebTolk/cfi&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Version for Joomla 3 and Joomla 4 (&lt;a href="https://joomline.ru/rasshirenija/plugin/cfi.html" rel="noopener noreferrer"&gt;https://joomline.ru/rasshirenija/plugin/cfi.html&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;GitHub Repository for Joomla 3+ versions (&lt;a href="https://github.com/AlekVolsk/cfi" rel="noopener noreferrer"&gt;https://github.com/AlekVolsk/cfi&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>joomla</category>
      <category>webdev</category>
      <category>seo</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Joomla View Logs component v.2.3.0 has been released!</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Sun, 11 Jan 2026 11:22:44 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/joomla-view-logs-component-v230-has-been-released-4a36</link>
      <guid>https://dev.to/sergeytolkachyov/joomla-view-logs-component-v230-has-been-released-4a36</guid>
      <description>&lt;p&gt;The component allows you to view error logs and notifications in the Joomla admin panel. Logs of both Joomla itself and extensions that use the standard kernel logger are displayed. It works with Joomla 4+, Joomla 5+.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujznvgh21tt2ameu39ha.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujznvgh21tt2ameu39ha.webp" alt="Joomla ViewLogs component admin panel" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  v.2.3.0 What's new?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The option to disable the display of the PHP log has been added in the component settings&lt;/li&gt;
&lt;li&gt;Added a message about the inability to delete a PHP log from the log list page&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added a link to download the zip archive in the message about archiving the log&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;disabled&lt;/code&gt; attribute has been added to the "archive" and "delete" buttons for the PHP log&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fixed the reading path for the PHP log&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fixed links for downloading logs in &lt;code&gt;csv&lt;/code&gt; format from the logs list page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fixed downloading logs in &lt;code&gt;csv&lt;/code&gt; format from the logs page (previously logs were downloaded with html code the template)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fixed translation of column headers of the log table&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://web-tolk.ru/en/dev/components/view-logs?utm_source=dev.to"&gt;Extension page&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/WebTolk/View-logs" rel="noopener noreferrer"&gt;Extension GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>joomla</category>
      <category>coding</category>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Joomla-дайджест. 2-е полугодие 2025 года.</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Sat, 03 Jan 2026 17:17:53 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/joomla-daidzhiest-2-ie-polughodiie-2025-ghoda-35nh</link>
      <guid>https://dev.to/sergeytolkachyov/joomla-daidzhiest-2-ie-polughodiie-2025-ghoda-35nh</guid>
      <description>&lt;p&gt;Все главные новости из мира Joomla с июля по декабрь 2025 года в одной статье. Я честно пытался напрячь самые разные ИИ сортировкой постов по смыслу и, к сожалению, ни один из них не справился с этой задачей так, как нужно мне. Поэтому, напрягая собственный интеллект, представляю читателю наш дайджест, который обозревает новости, расширения, шаблоны и статьи из мира Joomla. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://habr.com/ru/articles/982520/" rel="noopener noreferrer"&gt;Читать на Хабре&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>joomla</category>
      <category>digest</category>
      <category>russian</category>
    </item>
    <item>
      <title>WT IndexNow - send your Joomla urls to search engines via IndexNow protocol</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Sat, 03 Jan 2026 09:03:05 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/wt-indexnow-send-your-joomla-urls-to-search-engines-via-indexnow-protocol-590e</link>
      <guid>https://dev.to/sergeytolkachyov/wt-indexnow-send-your-joomla-urls-to-search-engines-via-indexnow-protocol-590e</guid>
      <description>&lt;p&gt;A free package of plugins that provides manual and automatic sending Joomla URLs to search engines for reindexing using the IndexNow protocol (&lt;a href="https://indexnow.org" rel="noopener noreferrer"&gt;https://indexnow.org&lt;/a&gt;).&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficpo45vs2dlqfmp0ic5m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficpo45vs2dlqfmp0ic5m.jpg" alt="indexNow joomla 6 plugins admin panel" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Supported components
&lt;/h2&gt;

&lt;p&gt;At the moment, the package includes providers for the following components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Joomla articles and aritcles categories&lt;/li&gt;
&lt;li&gt;Joomla contacts and contacts categories&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://web-tolk.ru/dev/components/sw-jprojects?utm_source=dev-to" rel="noopener noreferrer"&gt;SW JProjects&lt;/a&gt; &lt;a href="https://github.com/WebTolk/SWJProjects" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; &lt;a href="https://extensions.joomla.org/extensions/extension/authoring-a-content/content-construction/swjprojects/" rel="noopener noreferrer"&gt;Joomla Extensions Directory&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.webdesigner-profi.de/joomla-webdesign/shop.html" rel="noopener noreferrer"&gt;JoomShopping&lt;/a&gt; &lt;a href="https://extensions.joomla.org/extension/joomshopping/" rel="noopener noreferrer"&gt;Joomla Extensions Directory&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.phoca.cz/phocadownload" rel="noopener noreferrer"&gt;Phoca Download&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.phoca.cz/phocacart" rel="noopener noreferrer"&gt;Phoca Cart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://radicalmart.ru?utm_source=dev-to" rel="noopener noreferrer"&gt;RadicalMart&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1cyln8ocwtl9nfnx0l9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1cyln8ocwtl9nfnx0l9.jpg" alt="IndexNow in Joomla" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F275ktsnyv03zwhrsdieh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F275ktsnyv03zwhrsdieh.jpg" alt="Phoca Cart IndexNow button" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The plugin package is designed to send the URLs of Joomla sites to search engines for reindexing using the IndexNow. According to the documentation, the protocol is supported by all major search engines except Google. The protocol is used to receive URLs from sites that need to be reindexed or indexed for the first time as quickly as possible. Sending site addresses in this way will significantly speed up the indexing of new or modified content by search engines. Search engines use this protocol to exchange data with each other, so by sending a URL to one of them, you share it with everyone at once.&lt;/p&gt;

&lt;p&gt;Using the IndexNow protocol, no more than 10000 URLs can be sent per day. Keep this in mind when working with content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://extensions.joomla.org/extension/site-management/seo-a-metadata/wt-indexnow/" rel="noopener noreferrer"&gt;Joomla Extensisons Directory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web-tolk.ru/en/dev/joomla-plugins/wt-indexnow?utm_source=dev-to" rel="noopener noreferrer"&gt;Extension page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/WebTolk/WT-Index-now-joomla-package" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;See &lt;a href="https://www.youtube.com/watch?v=tLk_yxqks6s" rel="noopener noreferrer"&gt;YouTube video&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>joomla</category>
      <category>seo</category>
      <category>indexnow</category>
    </item>
    <item>
      <title>WT Yandex map items v.2.0.5 Joomla module has been released</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Wed, 30 Jul 2025 05:09:25 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/wt-yandex-map-items-v205-joomla-module-has-been-released-1350</link>
      <guid>https://dev.to/sergeytolkachyov/wt-yandex-map-items-v205-joomla-module-has-been-released-1350</guid>
      <description>&lt;p&gt;Display data from various component's custom fields like &lt;a href="https://yandex.com/maps" rel="noopener noreferrer"&gt;Yandex.Maps&lt;/a&gt; placemarks. Joomla articles are displayed as Yandex.maps placemarks. The articles categories and contacts are not displayed yet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo91thwvht1wefu6ft49n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo91thwvht1wefu6ft49n.png" alt="WT Yandex map items Joomla module screenshot" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  v.2.0.5. What's new?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  UX improving
&lt;/h3&gt;

&lt;p&gt;When interacting with a page on mobile devices, if the map is displayed in full width, it starts scrolling instead of the web page. To avoid this situation, an overlay for the map has been added. Now interaction with the map is possible after clicking on the map. The overlay automatically turns on when the cursor leaves the borders of the map container and the map can be scrolled again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web-tolk.ru/en/dev/joomla-modules/wt-yandex-map-items?utm_source=devto" rel="noopener noreferrer"&gt;Extension page&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/sergeytolkachyov/WT-Yandex-map-items-joomla-module" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>joomla</category>
      <category>webdev</category>
      <category>yandex</category>
      <category>map</category>
    </item>
    <item>
      <title>Joomla 5.2.4 Security &amp; Bugfix Release</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Wed, 19 Feb 2025 05:23:10 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/joomla-524-security-bugfix-release-4hpo</link>
      <guid>https://dev.to/sergeytolkachyov/joomla-524-security-bugfix-release-4hpo</guid>
      <description>&lt;p&gt;Let’s celebrate! The Joomla! Project is pleased to announce the release of Joomla 5.2.4 and Joomla 4.4.11. This is a security and bug fix release for the 5.x and 4.x series of Joomla.&lt;/p&gt;

&lt;p&gt;These releases continue Joomla’s high standards in accessible web design, highlighting Joomla's values of inclusiveness, simplicity and security into an even more powerful open-source web platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Fix
&lt;/h2&gt;

&lt;p&gt;[20250201] - Core - SQL injection vulnerability in Scheduled Tasks component. &lt;a href="https://developer.joomla.org/security-centre/958-20250201-core-sql-injection-vulnerability-in-scheduled-tasks-component.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug fixes and Improvements with 5.2.4
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fix namespace map creation on PHP 8.4 (#44789)&lt;/li&gt;
&lt;li&gt;Fix PHP Warning for debuguser, debuggroup (#44721)&lt;/li&gt;
&lt;li&gt;Fix handling of null values on update row (#39607)&lt;/li&gt;
&lt;li&gt;Fix cache counting issue - correctly count number of files (#43986)&lt;/li&gt;
&lt;li&gt;Fix permissions for manually running scheduled tasks (#36719)&lt;/li&gt;
&lt;li&gt;Tag Router: Allow numeric/CSV IDs (Regression) (#44784)&lt;/li&gt;
&lt;li&gt;Fix for Composer update to enshrined/svg-sanitize to resolve SVG upload issues (#44746)&lt;/li&gt;
&lt;li&gt;Fix for Article cannot be saved successfully on the front-end (#44680)&lt;/li&gt;
&lt;li&gt;Fix media downloads with spaces (Follow-up of #37396) (#44745)&lt;/li&gt;
&lt;li&gt;Finder Router: Filter out unnecessary query elements (#44055)&lt;/li&gt;
&lt;li&gt;Jooa11y plugin and page cache conflicts (#41956)&lt;/li&gt;
&lt;li&gt;Fix a11y issue in accordion (role attribute) (#40578)&lt;/li&gt;
&lt;li&gt;Remove alt-text for menu items when both image and title are set (a11y fix) (#40675)&lt;/li&gt;
&lt;li&gt;Fix breadcrumbs color in light and dark mode (#44212)&lt;/li&gt;
&lt;li&gt;Email alt text fix in contact component (#44491)&lt;/li&gt;
&lt;li&gt;Web Asset Manager: Incorrect loading of external resource with / at the end (#44774)&lt;/li&gt;
&lt;li&gt;Fix media downloads with spaces (Follow-up of #37396) (#44745)&lt;/li&gt;
&lt;li&gt;Fix multi-select behavior in Media Manager (Follow-up of #39824) (#44747)&lt;/li&gt;
&lt;li&gt;Fix error handling when creating folders in Media Manager (#39878)&lt;/li&gt;
&lt;li&gt;Fix assets for com_scheduler on new installations (#44684)&lt;/li&gt;
&lt;li&gt;Fix password reset broken in backend (#44723)&lt;/li&gt;
&lt;li&gt;Email cloak plugin fails for emails with IDN (Internationalized Domain Names) (#39888)&lt;/li&gt;
&lt;li&gt;Fix handling of root path removal only when it is at the beginning (#36685)&lt;/li&gt;
&lt;li&gt;Load the namespace from the cached manifest (Reverted) (#44755)&lt;/li&gt;
&lt;li&gt;Fix for Codemirror duplicated assets entries (#44674)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full list on GitHub is here: &lt;a href="https://github.com/joomla/joomla-cms/milestone/136?closed=1" rel="noopener noreferrer"&gt;https://github.com/joomla/joomla-cms/milestone/136?closed=1&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.joomla.org/announcements/release-news/5920-joomla-5-2-4-security-bugfix-release.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Joomla Community resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://joomla.org/" rel="noopener noreferrer"&gt;https://joomla.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.joomla.org/Mattermost" rel="noopener noreferrer"&gt;Joomla Community chat in Mattermost&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>joomla</category>
      <category>php</category>
      <category>coding</category>
    </item>
    <item>
      <title>Joomla tip: show notifications by Joomla.renderMessages</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Mon, 17 Feb 2025 13:49:06 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/joomla-tip-show-notifications-by-joomlarendermessages-13lm</link>
      <guid>https://dev.to/sergeytolkachyov/joomla-tip-show-notifications-by-joomlarendermessages-13lm</guid>
      <description>&lt;p&gt;The user performs some actions on the site and receives messages about the successful or unsuccessful result, as well as just informational messages. In php code, we are used to using the &lt;code&gt;enqueueMessage()&lt;/code&gt; method for this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\CMS\Factory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Message'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;Factory&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getApplication&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;enqueueMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'warning'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most often, language constants are used as messages so that users can receive messages in their own language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\CMS\Factory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\CMS\Language\Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Factory&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getApplication&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;enqueueMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SOME_LANG_CONSTANT'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'info'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rendering of Joomla messages in the frontend
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/vgQlk7OoLvE"&gt;
&lt;/iframe&gt;
&lt;br&gt;
Here we will need the connected core files &lt;code&gt;core.js&lt;/code&gt; and &lt;code&gt;messages.js&lt;/code&gt;. A little excerpt from the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Render messages send via JSON
 * Used by some javascripts such as validate.js
 *
 * @param   {object}  messages JavaScript object containing the messages to render.
 *          Example:
 *          const messages = {
 *              "message": ["This will be a green message", "So will this"],
 *              "error": ["This will be a red message", "So will this"],
 *              "info": ["This will be a blue message", "So will this"],
 *              "notice": ["This will be same as info message", "So will this"],
 *              "warning": ["This will be a orange message", "So will this"],
 *              "my_custom_type": ["This will be same as info message", "So will this"]
 *          };
 * @param  {string} selector The selector of the container where the message will be rendered
 * @param  {bool}   keepOld  If we shall discard old messages
 * @param  {int}    timeout  The milliseconds before the message self destruct
 * @return  void
 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what it looks like in practice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Joomla&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;renderMessages&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Joomla&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;COM_SWJPROJECTS_USER_KEYS_KEY_SUCCESSFULLY_COPYED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we see that we can use language constants as a message in Javascript. And that's cool! To do this, we use the &lt;code&gt;Joomla.Text._()&lt;/code&gt; method (similar to &lt;code&gt;Text::_()&lt;/code&gt; in PHP). But Javascript has to get the values of these language constants from somewhere. And to do this, in the php code of our page, we need to take care of it and add the language constants necessary for js using the &lt;code&gt;Text::script()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\CMS\Language\Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SOME_LANG_CONSTANT_SUCCESS'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SOME_LANG_CONSTANT_FAIL'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way I can access the values of the language constants &lt;code&gt;SOME_LANG_CONSTANT_SUCCESS&lt;/code&gt; and &lt;code&gt;SOME_LANG_CONSTANT_FAIL&lt;/code&gt; in javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Joomla Community resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://joomla.org/" rel="noopener noreferrer"&gt;https://joomla.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.joomla.org/Mattermost" rel="noopener noreferrer"&gt;Joomla Community chat in Mattermost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web-tolk.ru/en/dev" rel="noopener noreferrer"&gt;WebTolk Joomla extensions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web-tolk.ru/blog/sovet-po-joomla-pokaz-uvedomlenij-joomla-rendermessages" rel="noopener noreferrer"&gt;This article in Russian&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>joomla</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>coding</category>
    </item>
    <item>
      <title>Joomla tip: Use the Joomla\Uri\Uri class to create a URL.</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Thu, 16 Jan 2025 11:15:47 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/joomla-tip-use-the-joomlauriuri-class-to-create-a-url-7ib</link>
      <guid>https://dev.to/sergeytolkachyov/joomla-tip-use-the-joomlauriuri-class-to-create-a-url-7ib</guid>
      <description>&lt;p&gt;When building a url in the code, you can collect all the strings with concatenation of the form&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'/index.php?option='&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$option&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'&amp;amp;view='&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$view&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'&amp;amp;param1='&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$value1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and for small strings, it can even be convenient.  But if there are a lot of parameters or they require standardization/cleaning in the process, then not everything is so convenient and obvious. For example, there may be a leading slash in part of the url (a slash at the beginning of the url fragment) and the incoming domain for the request may also end in a slash, and so we get an incorrect url for the request with a double slash somewhere in the middle...&lt;/p&gt;

&lt;p&gt;For the tasks of standardization and uniformity of url retrieval, Joomla has the &lt;code&gt;Joomla\Uri\Uri&lt;/code&gt; class. Previously, with Joomla 1.6 and older, it was called &lt;code&gt;JUri&lt;/code&gt;. This class provides work with urls according to the &lt;strong&gt;RFC3986&lt;/strong&gt; standard and takes over the work of parsing URLs for spare parts or assembling URLs from spare parts))&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: get a specific parameter from the url.
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\Uri\Uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'https://web-tolk.ru/dev/biblioteki?param=value'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// output the line 'value' here&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'param'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, there is a native PHP function &lt;code&gt;parse_url&lt;/code&gt;, you might say... But the &lt;code&gt;Uri&lt;/code&gt; class ensures safe operation with UTF-8 in urls, including Cyrillic domains. In order not to write various checks yourself, you can use the features of the Joomla core.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to build required url in the code in Joomla
&lt;/h2&gt;

&lt;p&gt;Here, too, everything is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\Uri\Uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setHost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'web-tolk.ru'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setScheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// setPath() starts with leading slash&lt;/span&gt;
&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/dev/biblioteki'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// GET-parameters can be passed as an array&lt;/span&gt;
&lt;span class="nv"&gt;$vars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'param1'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'value1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'param2'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'value2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'param3'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'value3'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$vars&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// echo our url like string&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hierarchy of &lt;code&gt;Uri&lt;/code&gt; classes in Joomla is designed so that getter methods are in the &lt;code&gt;AbstractUri&lt;/code&gt; class, and setters are in the &lt;code&gt;Uri&lt;/code&gt; class. The setters can be viewed in the file &lt;strong&gt;libraries/vendor/joomla/uri/src/Uri.php&lt;/strong&gt; . We look at Hetaera in the file &lt;strong&gt;libraries/vendor/joomla/uri/src/AbstractUri.php&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;If you have PHPStorm, then it knows Joomla perfectly well and tells you everything you need.&lt;br&gt;
Well, you can give a link to the &lt;a href="https://docs.joomla.org/API16:JURI" rel="noopener noreferrer"&gt;old documentation page&lt;/a&gt;, which is still mostly relevant, adjusted for the use of namespaces.&lt;/p&gt;

&lt;p&gt;Uri structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     foo://example.com:8042/over/there?name=ferret#nose
     \_/   \______________/\_________/ \_________/ \__/
      |           |            |            |        |
   scheme     authority       path        query   fragment

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Joomla Community resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://joomla.org/" rel="noopener noreferrer"&gt;https://joomla.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.joomla.org/Mattermost" rel="noopener noreferrer"&gt;Joomla Community chat in Mattermost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web-tolk.ru/en/dev" rel="noopener noreferrer"&gt;WebTolk Joomla extensions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://habr.com/ru/articles/851520/" rel="noopener noreferrer"&gt;This article in Russian&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>joomla</category>
      <category>php</category>
      <category>coding</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The anatomy of smart search in Joomla 5. Creating a plugin Part 3</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Fri, 03 Jan 2025 06:29:11 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/the-anatomy-of-smart-search-in-joomla-5-creating-a-plugin-part-3-2931</link>
      <guid>https://dev.to/sergeytolkachyov/the-anatomy-of-smart-search-in-joomla-5-creating-a-plugin-part-3-2931</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/sergeytolkachyov/the-anatomy-of-smart-search-in-joomla-5-part-1-introduction-4mfo"&gt;first article&lt;/a&gt;, we got acquainted with the capabilities of the Joomla smart search component, talked about the parameters and configuration of scheduled indexing using CRON. And in the &lt;a href="https://dev.to/sergeytolkachyov/the-anatomy-of-smart-search-in-joomla-5-part-2-creating-a-plugin-i-2fch"&gt;second article&lt;/a&gt; we've started to code our custom plugin for Joomla smart search component. So, let's finish it!&lt;/p&gt;

&lt;h2&gt;
  
  
  The index() method
&lt;/h2&gt;

&lt;p&gt;This method should adapt the data obtained from the database in order to submit it for indexing. As an argument, the &lt;code&gt;$item&lt;/code&gt; element (article, product, tag, etc.) is passed to it as an instance class of the &lt;code&gt;\Joomla\Component\Finder\Administrator\Indexer\Result&lt;/code&gt; class. The properties of &lt;code&gt;$item&lt;/code&gt; match those that we selected from the database. The ultimate goal of this method is to call &lt;code&gt;$this-&amp;gt;indexer-&amp;gt;index($item)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You need to understand what the search results will look like in order to understand what to compare with what.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xi8swn5ngefurba099o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xi8swn5ngefurba099o.png" alt="Joomla 5 smart search result structure" width="800" height="153"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Joomla 5 smart search result structure&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here I take the names straight from the code. In this case, the images are not shown in the search results, but they are also there - &lt;code&gt;$this-&amp;gt;result-&amp;gt;imageUrl&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;imageUrl&lt;/strong&gt; - a picture of the Joomla article, product, tag, contact. It is displayed if enabled in the settings of the smart search component.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;title&lt;/strong&gt; - the title of the material, the name of the product, contact, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;description&lt;/strong&gt; and &lt;strong&gt;body&lt;/strong&gt; - a text description. We remember that many entities in Joomla have a short and complete description or an introductory and full text. Here they are combined and then trimmed to the character limit specified in the settings. &lt;strong&gt;body&lt;/strong&gt; is the full text or description.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;getTaxonomy()&lt;/strong&gt; - the method receives and outputs taxonomy data for a given search result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, we have few data visible to the user - only 4 types. And we get more data from the database. We need to understand which of them will be available for indexing by search, and which will only be displayed.&lt;/p&gt;

&lt;p&gt;Here is the code of the &lt;code&gt;index()&lt;/code&gt; method with comments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="cd"&gt;/**
 * Method to index an item. The item must be a Result object.
 *
 * @param   Result  $item  The item to index as a Result object.
 *
 * @return  void
 *     
 * @throws  \Exception on database error.
 * @since   2.5
 */&lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Setting the language of the indexed element - the default language of the site&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setLanguage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Check if JoomShopping is enabled in Joomla.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ComponentHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;isEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// We take part of the paths to the pictures from the component parameters.&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;loadJshopConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Setting the context for indexing&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'com_jshopping.product'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// We collect all the parameters in a bunch: the search component, JoomShopping and the site.&lt;/span&gt;
    &lt;span class="c1"&gt;// They will be available to us in the output layout&lt;/span&gt;
    &lt;span class="nv"&gt;$registry&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Registry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;clone&lt;/span&gt; &lt;span class="nc"&gt;ComponentHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'com_jshopping'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$registry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Registry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;jshopConfig&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="c1"&gt;// Meta-data: meta-keywords, meta description, author,&lt;/span&gt;
    &lt;span class="c1"&gt;// index / no-index values for robots&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Registry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Process the content with content plugins - the onContentPrepare event.&lt;/span&gt;
    &lt;span class="c1"&gt;// Content plugins always have a context check.&lt;/span&gt;
    &lt;span class="c1"&gt;// If it is equal to 'com_finder.indexer', then content plugins will usually not work.&lt;/span&gt;
    &lt;span class="c1"&gt;// ONLY TEXT should be given for indexing.&lt;/span&gt;
    &lt;span class="c1"&gt;// Neither pictures nor YouTube videos should get there, so&lt;/span&gt;
    &lt;span class="c1"&gt;// the indexed content will be cleared of HTML tags.&lt;/span&gt;
    &lt;span class="c1"&gt;// The raw short codes are just text and can get&lt;/span&gt;
    &lt;span class="c1"&gt;// into the search results.&lt;/span&gt;

    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Helper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prepareContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Helper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prepareContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Include here JoomShopping classed.&lt;/span&gt;
    &lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="no"&gt;JPATH_SITE&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/components/com_jshopping/bootstrap.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;\JSFactory&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;loadAdminLanguageFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;languageTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="c1"&gt;// A trick. We want to be able to search by price, product code, etc too.&lt;/span&gt;
    &lt;span class="c1"&gt;// Attaching all this data to the body.&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;

    &lt;span class="c1"&gt;// Manufacturer code&lt;/span&gt;
    &lt;span class="nv"&gt;$manufacturer_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'manufacturer_code'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$manufacturer_code&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JSHOP_MANUFACTURER_CODE'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;': '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$manufacturer_code&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// EAN&lt;/span&gt;
    &lt;span class="nv"&gt;$product_ean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'product_ean'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product_ean&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JSHOP_EAN'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;': '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$product_ean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Old price&lt;/span&gt;
    &lt;span class="nv"&gt;$product_old_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'product_old_price'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product_old_price&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$product_old_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;\JSHElper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;formatPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'product_old_price'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;        &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JSHOP_OLD_PRICE'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;': '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$product_old_price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Buy price&lt;/span&gt;
    &lt;span class="nv"&gt;$product_buy_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'product_buy_price'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product_buy_price&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$product_buy_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;\JSHElper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;formatPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'product_buy_price'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;        &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JSHOP_PRODUCT_BUY_PRICE'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;': '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$product_buy_price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Price&lt;/span&gt;
    &lt;span class="nv"&gt;$product_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'product_price'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product_price&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$product_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;\JSHElper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;formatPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product_price&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;    &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JSHOP_PRODUCT_PRICE'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;': '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$product_price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="c1"&gt;// URL - the unique key of the element in the table. Read more about this after the sample code&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'com_jshopping'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;catslug&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Link to element - to JoomShopping product&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// A menu item can be created for product. Menu item has own page header.&lt;/span&gt;
    &lt;span class="c1"&gt;// Joomla menu has higher priority then we'll take data from it.&lt;/span&gt;
    &lt;span class="nv"&gt;$title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getItemMenuTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Adjust the title if necessary.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'use_menu_title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Add product image&lt;/span&gt;
    &lt;span class="nv"&gt;$product_image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'image'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product_image&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;imageUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'image_product_live_path'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$product_image&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;imageAlt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// The product has no author. But you can do this if you search by author/user&lt;/span&gt;
    &lt;span class="c1"&gt;// For example, you enabled search by author in the smart search component settings&lt;/span&gt;
    &lt;span class="c1"&gt;// and it should search for everything related to this author&lt;/span&gt;
    &lt;span class="c1"&gt;// $item-&amp;gt;metaauthor = $item-&amp;gt;metadata-&amp;gt;get('author');&lt;/span&gt;

    &lt;span class="c1"&gt;// Add the metadata processing instructions.&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addInstruction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Indexer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;META_CONTEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'metakey'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addInstruction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Indexer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;META_CONTEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'metadesc'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// $item-&amp;gt;addInstruction(Indexer::META_COTNTEXT, 'metaauthor');&lt;/span&gt;
    &lt;span class="c1"&gt;// $item-&amp;gt;addInstruction(Indexer::META_CONTEXT, 'author');&lt;/span&gt;
    &lt;span class="c1"&gt;// $item-&amp;gt;addInstruction(Indexer::META_CONTEXT, 'created_by_alias');&lt;/span&gt;

    &lt;span class="c1"&gt;// Access group for the default search result.&lt;/span&gt;
    &lt;span class="c1"&gt;// We hardcode "1" - that is, for everyone. But here you can&lt;/span&gt;
    &lt;span class="c1"&gt;// take the access group from the product.&lt;/span&gt;
    &lt;span class="c1"&gt;// Or show different search results to different access groups.&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Check if the category for the product is published.&lt;/span&gt;
    &lt;span class="c1"&gt;// Products should only be published if their category is published.&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;translateState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cat_state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Get the list of taxonomies to display from the plugin parameters&lt;/span&gt;
    &lt;span class="nv"&gt;$taxonomies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'taxonomies'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'product'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'category'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'language'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="c1"&gt;// Name of the search type in the drop-down list of types: materials, contacts.&lt;/span&gt;
    &lt;span class="c1"&gt;// In our case - product. We take a language constant for this.&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addTaxonomy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Type'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JSHOP_PRODUCT'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="c1"&gt;// Add product categories to the drop-down list&lt;/span&gt;
    &lt;span class="c1"&gt;// categories so that you can search only in a specific&lt;/span&gt;
    &lt;span class="c1"&gt;// categories. Here we already transfer the names of the categories.&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addTaxonomy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Category'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Search only in the desired language&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addTaxonomy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Language'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getLangTag&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="c1"&gt;// Search results can be limited by publication start and end dates&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;publish_start_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Factory&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;getDate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toSql&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;start_date&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Factory&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;getDate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toSql&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Add additional data for the indexed element.&lt;/span&gt;
    &lt;span class="c1"&gt;// Here in the helper the "onPrepareFinderContent" event is called&lt;/span&gt;
    &lt;span class="c1"&gt;// This is usually how comments, tags, labels&lt;/span&gt;
    &lt;span class="c1"&gt;// and other things that should be available for search are added.&lt;/span&gt;
    &lt;span class="c1"&gt;// Accordingly, individual plugins work with this event.&lt;/span&gt;
    &lt;span class="c1"&gt;// In our case, we do not need this yet.&lt;/span&gt;
    &lt;span class="c1"&gt;// Helper::getContentExtras($item);&lt;/span&gt;

    &lt;span class="c1"&gt;// Add custom fields (com_fields) Joomla, if the component&lt;/span&gt;
    &lt;span class="c1"&gt;// supports them.&lt;/span&gt;
    &lt;span class="c1"&gt;// In our case, we do not need this yet.&lt;/span&gt;
    &lt;span class="c1"&gt;// Helper::addCustomFields($item, 'com_jshopping.product');&lt;/span&gt;

    &lt;span class="c1"&gt;// Index the item.&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;indexer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Types of instructions for "marking up the weight" of content for indexing.
&lt;/h2&gt;

&lt;p&gt;I am not an expert in fine-tuning indexing, so I will try to describe what I could see in the code. In the parameters of the smart search component, there are weight settings for each part of the indexed content: title, main text, metadata, url, additional text.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1esuihhwyqs019ne2dzj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1esuihhwyqs019ne2dzj.png" alt="Joomla 5 smart search params - indexing weight settings for title, body, metadata" width="800" height="545"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Joomla 5 smart search params - indexing weight settings for title, body, metadata&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We have already seen these settings above in the first article in seria, but for convenience we will repeat the screenshot.&lt;/p&gt;

&lt;p&gt;In our smart search plugin, we can specify which data in our object for indexing belongs to which type by adding instructions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// In the index() method&lt;/span&gt;
&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addInstruction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Indexer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TEXT_CONTEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'product_buy_price'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We look at the types of context for instructions and their names by default in the class &lt;code&gt;\Joomla\Component\Finder\Administrator\Indexer\Result&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1v82vex2784mq1mj2ct.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1v82vex2784mq1mj2ct.png" alt="Joomla smart search indexing instructions types for weight markup" width="581" height="251"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Joomla smart search indexing instructions types for weight markup&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As I later found out, &lt;code&gt;list_price&lt;/code&gt; and &lt;code&gt;sale_price&lt;/code&gt; refer to indexing, not to the terminology of an online store.&lt;/p&gt;
&lt;h2&gt;
  
  
  getUrl() method
&lt;/h2&gt;

&lt;p&gt;The unique key for searching is essentially the url of the element in its system form: &lt;strong&gt;index.php?option=com_content&amp;amp;view=article&amp;amp;id=1&lt;/strong&gt;. In the database in the &lt;strong&gt;#__finder_links&lt;/strong&gt; table, it is stored in the &lt;strong&gt;url&lt;/strong&gt; column. But to build a link in the frontend to the desired element from the search results, a more complex option is used with a combination of id and aliases in the url: &lt;strong&gt;index.php?option=com_content&amp;amp;view=article&amp;amp;id=1:article-alias&amp;amp;catid=2&lt;/strong&gt;, which is stored in the adjacent route column. But Joomla routing will determine the final url without specifying an alias, in which case the content of the url and route will be the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// Fragment of index() method of smart search plugin for Joomla materials&lt;/span&gt;

&lt;span class="c1"&gt;// Create a URL as identifier to recognise items again.&lt;/span&gt;
&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Build the necessary route and path information.&lt;/span&gt;
&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RouteHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getArticleRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;catid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system url for the indexed element looks different in different components. In the components that follow the "Joomla way", you can use one controller, which, if no specific controller is found, will immediately show the desired &lt;code&gt;View&lt;/code&gt;. Therefore, in standard Joomla components, we usually do not find links indicating the controller in the GET parameters. They will all look like &lt;strong&gt;index.php?option=com_content&amp;amp;view=article&amp;amp;id=15&lt;/strong&gt;. This is the url that the &lt;code&gt;getUrl()&lt;/code&gt; method of the &lt;code&gt;Adapter&lt;/code&gt; class returns to us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="cd"&gt;/**
 * Method to get the URL for the item. The URL is how we look up the link
 * in the Finder index.
 *
 * @param   integer  $id         The id of the item.
 * @param   string   $extension  The extension the category is in.
 * @param   string   $view       The view for the URL.
 *
 * @return  string  The URL of the item.
 *
 * @since   2.5
 */&lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$extension&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'index.php?option='&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$extension&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;view='&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$view&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;id='&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, JoomShopping has its own story and URLs are built somewhat differently. We will not be able to use the standard method and we are redefining it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\CMS\Uri\Uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * @param string $product_id  Product id
 * @param string $extension  Always 'com_jshopping'
 * @param string $view  Not used for JoomShopping
 *
 * @return string
 *
 * @since 1.0.0
 */&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$extension&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'not_used'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * There is the trick. For JoomShopping product url construction
     * we need only in product id and category id
     */&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;loadJshopConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Keeping in mind the difficulties with categories in JoomShopping&lt;/span&gt;
    &lt;span class="c1"&gt;// we separate the process of getting the category into a separate method.&lt;/span&gt;
    &lt;span class="nv"&gt;$category_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getProductCategoryId&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$product_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'index.php'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setQuery&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'option'&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'com_jshopping'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'controller'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'product'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'task'&lt;/span&gt;        &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'view'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'category_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$category_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'product_id'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="c1"&gt;// When constructing a url in JoomShopping, it is advisable to find and specify&lt;/span&gt;
    &lt;span class="c1"&gt;// The correct itemId is the id of the menu item for JoomShopping.&lt;/span&gt;
    &lt;span class="c1"&gt;// Otherwise, we may have duplicate pages by url&lt;/span&gt;
    &lt;span class="c1"&gt;// We connected the JoomShopping API earlier, so the JSHelper should already be here.&lt;/span&gt;
    &lt;span class="nv"&gt;$defaultItemid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;\JSHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getDefaultItemid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Itemid'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$defaultItemid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  An atypical implementation of multilingualism. Indexation.
&lt;/h2&gt;

&lt;p&gt;Let's return to the problem of multilingualism, in which we do not have a separate indexed entity for each content language. But there is an indexed entity that contains values for all languages at once.&lt;/p&gt;

&lt;p&gt;The solution is to get a list of all languages inside the &lt;code&gt;index()&lt;/code&gt; method, collect the &lt;code&gt;Result&lt;/code&gt; object for each language and then give each object for indexing. We need to divide the data into those that are the same for both languages (usually &lt;code&gt;catid&lt;/code&gt;, &lt;code&gt;access&lt;/code&gt;, etc.) and different (&lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;fulltext&lt;/code&gt; etc.). That is, the &lt;code&gt;$this-&amp;gt;indexer-&amp;gt;index()&lt;/code&gt; method will be called several times inside the &lt;code&gt;Index()&lt;/code&gt; method of our plugin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="cd"&gt;/**
 * Method to index an item. The item must be a Result object.
 *
 * @param   Result  $item  The item to index as a Result object.
 *
 * @return  void
 *
 * @throws  \Exception on database error.
 * @since   2.5
 */&lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Initialise the item parameters.&lt;/span&gt;
    &lt;span class="nv"&gt;$registry&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Registry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;clone&lt;/span&gt; &lt;span class="nc"&gt;ComponentHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'com_swjprojects'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$registry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'com_swjprojects.project'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$lang_codes&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LanguageHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getLanguages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'lang_code'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$translates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getTranslateProjects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;catid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Translate the state. projects should only be published if the category is published.&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;translateState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cat_state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Get taxonomies to display&lt;/span&gt;
    &lt;span class="nv"&gt;$taxonomies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'taxonomies'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'category'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'language'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="c1"&gt;// Add the type taxonomy data.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\in_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$taxonomies&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addTaxonomy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Type'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Project'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$translates&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$translate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$translate&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$translate&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// Trigger the onContentPrepare event.&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Helper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prepareContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$translate&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;introtext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Helper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prepareContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$translate&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;fulltext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$metadata&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Registry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$translate&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;metakey&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'keywords'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;metadesc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$translate&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;introtext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Add the metadata processing instructions.&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addInstruction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Indexer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;META_CONTEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'metakey'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addInstruction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Indexer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;META_CONTEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'metadesc'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Multilanguage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;isEnabled&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$lang_codes&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$lang_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$translate&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$lang_code&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lang_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nv"&gt;$lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$lang_code&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;sef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Create a URL as identifier to recognise items again.&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;extension&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$lang&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Build the necessary route and path information.&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RouteHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getProjectRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;catid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Get the menu title if it exists.&lt;/span&gt;
        &lt;span class="nv"&gt;$title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getItemMenuTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Adjust the title if necessary.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'use_menu_title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Add the category taxonomy data.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\in_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'category'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$taxonomies&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addTaxonomy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Category'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$translate&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Add the language taxonomy data.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\in_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'language'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$taxonomies&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addTaxonomy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Language'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;


        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Registry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$icon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImagesHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'projects'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'icon'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Add the image.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$icon&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;imageUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$icon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;imageAlt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Add the meta author.&lt;/span&gt;
        &lt;span class="c1"&gt;// $item-&amp;gt;metaauthor = $item-&amp;gt;metadata-&amp;gt;get('author');&lt;/span&gt;

        &lt;span class="c1"&gt;// Get content extras.&lt;/span&gt;
        &lt;span class="c1"&gt;// Helper::getContentExtras($item);&lt;/span&gt;
        &lt;span class="c1"&gt;// Helper::addCustomFields($item, 'com_swjprojects.project');&lt;/span&gt;

        &lt;span class="c1"&gt;// Index the item.&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;indexer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to unify the value for the &lt;code&gt;route&lt;/code&gt; field for each language, so we make our own implementation of the &lt;code&gt;getUrl()&lt;/code&gt; method and add the &lt;code&gt;$lang&lt;/code&gt; parameter to the url.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="cd"&gt;/**
 * @param   int     $id
 * @param   string  $extension
 * @param   string  $view
 * @param   string  $lang  Language SEF code like `ru`, `en` etc
 *
 * @return string
 *
 * @since 2.1.0
 */&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$extension&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'index.php?option='&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$extension&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;view='&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$view&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;id='&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$lang&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;lang='&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$lang&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  getItems() and getContentCount() methods
&lt;/h2&gt;

&lt;p&gt;In general, we don't need anything else for manual indexing and reindexing of content, as well as scheduled via the CLI. However, if we come across some very unusual beast in the form of non-Joomla data, some third-party database, then we can completely redefine the logic of the parent Adapter class for these purposes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;getContentCount()&lt;/code&gt; - the method should return an integer - the number of indexed elements.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getItems($offset, $limit, $query = null)&lt;/code&gt; - under the hood, calls &lt;code&gt;getListQuery()&lt;/code&gt; and sets &lt;code&gt;$offset&lt;/code&gt; and &lt;code&gt;$limit&lt;/code&gt;, brings everything to a single view - objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If using one &lt;code&gt;getListQuery()&lt;/code&gt; method and accessing it from 3 other methods is inconvenient for some reason, you can customize requests and their processing in redefined methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reindexing content on the fly
&lt;/h2&gt;

&lt;p&gt;To solve this problem, we have several ways, two of which are the periodic manual and CRON indexing, as I wrote above. However, this is fraught with an untimely index update and site users may not receive updated data in search results on time. Therefore, there is another way: &lt;strong&gt;reindexing the content on the fly, immediately after saving the changes&lt;/strong&gt;. To do this, a &lt;strong&gt;content group&lt;/strong&gt; plugin is created, which triggers smart search plugin events at the right moments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjs3ezc4vx5xdstir1kpp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjs3ezc4vx5xdstir1kpp.png" alt="Content plugin for joomla smart search" width="800" height="494"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Content plugin for joomla smart search&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standard Joomla Model Events.&lt;/strong&gt;&lt;br&gt;
If the component is written according to the canons of Joomla and inherits its classes, then many models (&lt;code&gt;Model&lt;/code&gt; - MVC) trigger standard events, among which we are interested in several:&lt;br&gt;
onContentBeforeSave - The event is triggered before any Joomla entity is saved.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;onContentAfterSave&lt;/code&gt; - The event is triggered after saving any Joomla entity.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onContentAfterDelete&lt;/code&gt; - The event is triggered after deleting any Joomla entity.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onContentChangeState&lt;/code&gt; - the event is triggered after a state change (unpublished/published).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onCategoryChangeState&lt;/code&gt; - The event is triggered after the category status changes (if the standard Joomla categories component is used).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default, the smart search plugin causes the content to be reindexed at the listed points in time. In each of these events, the context of the event call is passed in the form of &lt;code&gt;&amp;lt;component&amp;gt;.&amp;lt;entity&amp;gt;&lt;/code&gt;, for example, &lt;code&gt;com_content.article&lt;/code&gt; or &lt;code&gt;com_menus.menu&lt;/code&gt;. According to the desired context, you can determine whether to start reindexing or not. We are already doing this check in the smart search plugin. An example from the code of the Finder content plugin for Joomla articles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\CMS\Event\Finder&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;FinderEvent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Smart Search after save content method.
 * Content is passed by reference, but after the save, so no changes will be saved.
 * Method is called right after the content is saved.
 *
 * @param   string  $context  The context of the content passed to the plugin (added in 1.6)
 * @param   object  $article  A \Joomla\CMS\Table\Table\ object
 * @param   bool    $isNew    If the content has just been created
 *
 * @return  void
 *
 * @since   2.5
 */&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;onContentAfterSave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$isNew&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;importFinderPlugins&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Trigger the onFinderAfterSave event.&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getDispatcher&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'onFinderAfterSave'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FinderEvent\AfterSaveEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'onFinderAfterSave'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'context'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'subject'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$article&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'isNew'&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$isNew&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, the &lt;code&gt;onFinderAfterSave&lt;/code&gt; event is called here, which is specific specifically for smart search plugins. And in the &lt;code&gt;onFinderAfterSave()&lt;/code&gt; method of our smart search plugin, there is already a check for the desired context and reindexing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\CMS\Event\Finder&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;FinderEvent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Smart Search after save content method.
 * Reindexes the link information for an article that has been saved.
 * It also makes adjustments if the access level of an item or the
 * category to which it belongs has changed.
 *
 * @param   FinderEvent\AfterSaveEvent   $event  The event instance.
 *
 * @return  void
 *
 * @since   2.5
 * @throws  \Exception on database error.
 */&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;onFinderAfterSave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FinderEvent&lt;/span&gt;&lt;span class="nc"&gt;\AfterSaveEvent&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$row&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$isNew&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getIsNew&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// We only want to handle articles here.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$context&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'com_content.article'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$context&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'com_content.form'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Check if the access levels are different.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$isNew&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;old_access&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;access&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Process the change.&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;itemAccessChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Reindex the item.&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;reindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Check for access changes in the category.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$context&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'com_categories.category'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Check if the access levels are different.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$isNew&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;old_cataccess&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;access&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;categoryAccessChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the same way, the work is organized when the state changes and the article or product is deleted.&lt;/p&gt;

&lt;h2&gt;
  
  
  getItem() method
&lt;/h2&gt;

&lt;p&gt;This method gets the indexed element by its &lt;code&gt;id&lt;/code&gt;. It is called when reindexing after saving articles, products, etc. - on the &lt;code&gt;onFinderAfterSave&lt;/code&gt; event. Internally, it receives an SQL query from the &lt;code&gt;getListQuery()&lt;/code&gt; method, adds the &lt;code&gt;id&lt;/code&gt; of the requested entity to it, and executes the query. However, in the parent class, the &lt;code&gt;id&lt;/code&gt; field with the prefix &lt;code&gt;a&lt;/code&gt; is hardcoded for tables - &lt;code&gt;$query-&amp;gt;where('a.id = ' . (int) $id)&lt;/code&gt;. Since in our case both the prefix and the name of the field for the request are different, we redefine the method too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// I have indicated here only the namespaces used in the example&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\Utilities\ArrayHelper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\Component\Finder\Administrator\Indexer\Result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Method to get a content item to index.
 *
 * @param   integer  $id  The id of the content item.
 *
 * @return  Result  A Result object.
 *
 * @throws  \Exception on database error.
 * @since   2.5
 */&lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Get the list query and add the extra WHERE clause.&lt;/span&gt;
    &lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getListQuery&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'prod.product_id = '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Get the item to index.&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;loadAssoc&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Convert the item to a result object.&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ArrayHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;toObject&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Set the item type.&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;type_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;type_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Set the item layout.&lt;/span&gt;
    &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This articles seria does not pretend to be a complete description of the mechanics of smart search in Joomla, even after 4 months of work on it. And in this case it is not a metaphor. But I hope this article will help those who will take up writing plugins for indexing data from Joomla components or third-party systems.&lt;/p&gt;

&lt;p&gt;I will gratefully accept suggestions for improving the article and additions in the comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Joomla Community resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://joomla.org/" rel="noopener noreferrer"&gt;https://joomla.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://magazine.joomla.org/all-issues/december-2024/the-anatomy-of-smart-search-in-joomla-5-part-2-creating-a-plugin-ii" rel="noopener noreferrer"&gt;This article in Joomla Community Magazine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Joomla Community chat in Mattermost (&lt;a href="https://docs.joomla.org/Mattermost" rel="noopener noreferrer"&gt;read more&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>joomla</category>
      <category>php</category>
      <category>webdev</category>
      <category>search</category>
    </item>
    <item>
      <title>Connecting third-party PHP libraries in Joomla</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Fri, 27 Dec 2024 07:23:03 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/connecting-third-party-php-libraries-in-joomla-4mdl</link>
      <guid>https://dev.to/sergeytolkachyov/connecting-third-party-php-libraries-in-joomla-4mdl</guid>
      <description>&lt;p&gt;PHP libraries are convenient because they can be accessed from anywhere in the Application: from a plugin, component model, module, etc. If someone has already solved a similar problem and designed it as a library (and even updates it), it makes sense to connect this library to your Joomla. For example, to develop a payment method for an online store, you need the official library of a payment aggregator. Or are you satisfied with the official PHP SDK of some CRM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composer
&lt;/h2&gt;

&lt;p&gt;Joomla does not support working with Composer directly. In order to use the library in your work, you need to "wrap" it in a Joomla extension type &lt;code&gt;library&lt;/code&gt; and install it. In serious projects, the approach of fixing versions of all components of the project is adopted: the code has been checked more than once, tested and allowed to work in the production.&lt;/p&gt;

&lt;p&gt;You create a package with your library, install it wherever you need it. As new versions of the library are released, you update your wrapper and get all the advantages of working with Joomla extensions: updating extensions in the standard way, including through the CLI. View the Changelog of the extension in the admin area BEFORE updating, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38olm6xgj8zoktk5xrs1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38olm6xgj8zoktk5xrs1.png" alt="View the Changelog extension in the admin area BEFORE updating to Joomla 5." width="800" height="431"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;View the Changelog extension in the admin area BEFORE updating to Joomla 5.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Joomla, PSR, Symfony
&lt;/h2&gt;

&lt;p&gt;Joomla complies with PSR standards, so it is convenient to work with it in this regard. Some Symfony packages are included in the Joomla core (&lt;code&gt;console&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;vardumper&lt;/code&gt;, &lt;code&gt;yaml&lt;/code&gt;, &lt;code&gt;error-handler&lt;/code&gt; and others), so if you suddenly want to add more, they will fit in and work well. You can see what else is worth in Joomla besides Symfony components in &lt;code&gt;libraries/vendor&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to wrap a 3rd-party PHP library in a Joomla extension?
&lt;/h2&gt;

&lt;p&gt;Nothing complicated. The library files are usually located in the &lt;code&gt;src&lt;/code&gt; folder. Next to this folder, you need to create an XML manifest of the Joomla extension according to the documentation (&lt;a href="https://manual.joomla.org/docs/building-extensions/install-update/installation/manifest" rel="noopener noreferrer"&gt;manual.joomla.org&lt;/a&gt;). Then we pack everything into a zip archive and that's it! It can be installed.&lt;/p&gt;

&lt;p&gt;If you need your own tables in the database for the library to work, you need to add the necessary files with SQL queries during installation or update. Since Joomla 4+ works with namespaces, it is important to specify this namespace in the XML manifest for the extension. Here is an abbreviated example of an XML manifest for the Joomla library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" ?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;extension&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"library"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"upgrade"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;WebTolk AmoCRM library&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;libraryname&amp;gt;&lt;/span&gt;Webtolk/Amocrm&lt;span class="nt"&gt;&amp;lt;/libraryname&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.2.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
     ...
     &lt;span class="nt"&gt;&amp;lt;namespace&lt;/span&gt; &lt;span class="na"&gt;path=&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Webtolk\Amocrm&lt;span class="nt"&gt;&amp;lt;/namespace&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;files&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;folder&amp;gt;&lt;/span&gt;src&lt;span class="nt"&gt;&amp;lt;/folder&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;filename&amp;gt;&lt;/span&gt;amocrm.xml&lt;span class="nt"&gt;&amp;lt;/filename&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/files&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/extension&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;lt;libraryname&amp;gt;&lt;/code&gt; tag means that the &lt;code&gt;src&lt;/code&gt; folder from our archive will be copied to &lt;code&gt;JPATH_SITE/libraries/Webtolk/Amocrm&lt;/code&gt;. In the &lt;code&gt;&amp;lt;files&amp;gt;&lt;/code&gt; section, we indicate what needs to be filled in from the archive. And &lt;code&gt;&amp;lt;namespace path="src"&amp;gt;Webtolk\Amocrm&amp;lt;/namespace&amp;gt;&lt;/code&gt; says that the namespace &lt;code&gt;Webtolk\Amocrm&lt;/code&gt; must be registered for the &lt;code&gt;src&lt;/code&gt; folder in &lt;code&gt;JPATH_SITE/libraries/Webtolk/Amocrm&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important notes!
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before Joomla 4.2.7, in fact, the tag &lt;code&gt;&amp;lt;namespace&amp;gt;&lt;/code&gt; from the XML manifest did not work.&lt;/strong&gt; Therefore, it was necessary to add a system plugin to the library package that would register the namespace on the &lt;code&gt;onAfterInitialize&lt;/code&gt; event (Event Dispatcher) using &lt;code&gt;JLoader&lt;/code&gt; class. Accordingly, it was necessary to build a package from the library and the plugin. &lt;strong&gt;Starting with Joomla 4.2.7, it has been fixed and you can do without the plugin.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;So far, updating the library = reinstalling.&lt;/strong&gt; That is, the extension is removed and installed. This decision was made somewhere in the depths of the versions of Joomla 3.x. Why? - hidden under the mountains of PR. We need to search. Why is this important? Because when installing any extension, an entry is created in the "registry" of extensions - in the database in the &lt;code&gt;#__extensions&lt;/code&gt; table. This table has 2 columns of type &lt;code&gt;TEXT&lt;/code&gt; - &lt;code&gt;params&lt;/code&gt; and &lt;code&gt;custom_data&lt;/code&gt;. And this, you must admit, is a considerable amount of data. If you store some library parameters in a database using &lt;code&gt;Joomla\CMS\Helper\LibraryHelper&lt;/code&gt;, then you need to take this behavior of the installer into account and pre-save and then add the saved parameters back to the extension's installer script when updating the library.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\CMS\Helper\LibraryHelper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\CMS\Cache\Cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Function called before extension installation/update/removal procedure commences.
 *
 * @param   string            $type     The type of change (install or discover_install, update, uninstall)
 * @param   InstallerAdapter  $adapter  The adapter calling this method
 *
 * @return  boolean  True on success
 *
 * @since   1.0.0
 */&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;preflight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;InstallerAdapter&lt;/span&gt; &lt;span class="nv"&gt;$adapter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'uninstall'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     *
     *  Joomla when updating extensions of the library type, it actually deletes them (along with the data in the database),
     *  and then installs it again.
     *  In order to avoid losing library data from the database, we are writing this crutch.
     *
     * @see https://github.com/joomla/joomla-cms/issues/39360
     *
     */&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'update'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$lib_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LibraryHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Webtolk/Amocrm'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$jconfig&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$options&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'defaultgroup'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'wt_amo_crm_temp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'caching'&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'cachebase'&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$jconfig&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cache_path'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'storage'&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$jconfig&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cache_handler'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$cache&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$cache&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$lib_params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'wt_amo_crm_temp'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the &lt;code&gt;postflight()&lt;/code&gt; method accordingly, we put the saved parameters back using &lt;code&gt;LibraryHelper::saveParams('Webtolk/Amocrm', $lib_params);&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;For the library to work, it must be enabled in the extension manager&lt;/strong&gt; (Menu - System - Management - Extensions).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Often, certain parameters (API keys, tokens, etc.) are needed for the library to work, which must be specified by people in the Joomla admin area.&lt;/strong&gt; For these purposes, it is convenient to write a plugin (an extension type &lt;code&gt;library&lt;/code&gt; does not have its own interface for configuring parameters). Either the system one or your own custom group doesn't matter. Inside your library, you can get plugin parameters pretty quickly like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\CMS\Plugin\PluginHelper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\Registry\Registry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PluginHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;isEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'system'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'wt_amocrm'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$plugin&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PluginHelper&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'system'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'wt_amocrm'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;$params&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;\json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$plugin&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;$param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;// OR you can use Joomla\Registry\Registry&lt;/span&gt;
      &lt;span class="nv"&gt;$params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Registry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$plugin&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nv"&gt;$param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'param'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'defatul value if empty'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Joomla Community resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://joomla.org/" rel="noopener noreferrer"&gt;https://joomla.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.joomla.org/Mattermost" rel="noopener noreferrer"&gt;Joomla Community chat in Mattermost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web-tolk.ru/en/dev" rel="noopener noreferrer"&gt;WebTolk Joomla extensions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://habr.com/ru/articles/851520/" rel="noopener noreferrer"&gt;This article in Russian&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>joomla</category>
      <category>php</category>
      <category>webdev</category>
      <category>coding</category>
    </item>
    <item>
      <title>Preparing extensions for Joomla 6. CMSObject -&gt; stdClass.</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Sat, 21 Dec 2024 14:35:13 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/preparing-extensions-for-joomla-6-cmsobject-stdclass-1p98</link>
      <guid>https://dev.to/sergeytolkachyov/preparing-extensions-for-joomla-6-cmsobject-stdclass-1p98</guid>
      <description>&lt;p&gt;In Joomla 6, the &lt;code&gt;getItem()&lt;/code&gt; method in &lt;code&gt;Adminmodel&lt;/code&gt; will return &lt;code&gt;\stdClass&lt;/code&gt; instead of &lt;code&gt;CMSObject&lt;/code&gt;.  This means that all deprecated functions of this class will be unavailable. Developers in Joomla 6 should work directly with the properties of the item object and not use the outdated &lt;code&gt;set()&lt;/code&gt; and &lt;code&gt;get()&lt;/code&gt; methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Old Joomla way
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;bootComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMVCFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Article'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Administrator'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$article&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How it will be in Joomla 6
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;bootComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMVCFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Article'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Administrator'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$article&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The corresponding Pull Request has already been accepted into the Joomla 6 branch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/joomla/joomla-cms/pull/42717" rel="noopener noreferrer"&gt;PR on Joomla GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Joomla Community resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://joomla.org/" rel="noopener noreferrer"&gt;https://joomla.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.joomla.org/Mattermost" rel="noopener noreferrer"&gt;Joomla Community chat in Mattermost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web-tolk.ru/en/dev" rel="noopener noreferrer"&gt;WebTolk Joomla extensions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>joomla</category>
      <category>webdev</category>
      <category>php</category>
      <category>development</category>
    </item>
    <item>
      <title>Getting the current user's object - Current User Trait in Joomla 4.2+</title>
      <dc:creator>Sergey Tolkachyov</dc:creator>
      <pubDate>Tue, 10 Dec 2024 08:14:42 +0000</pubDate>
      <link>https://dev.to/sergeytolkachyov/getting-the-current-users-object-current-user-trait-in-joomla-42-2j5o</link>
      <guid>https://dev.to/sergeytolkachyov/getting-the-current-users-object-current-user-trait-in-joomla-42-2j5o</guid>
      <description>&lt;p&gt;Traits are fragments of code that are disconnected from the context and can be used in a variety of places. They add their methods to your own classes. So, when developing extensions, sometimes you need to work with the current user of the site: is he a guest or an authorized one?  If authorized, which access group does it belong to? Etc. &lt;/p&gt;

&lt;p&gt;Starting with Joomla 4.2, the &lt;code&gt;CurrentUserTrait&lt;/code&gt; trade appeared in the kernel, which adds 2 methods &lt;code&gt;getCurrentUser()&lt;/code&gt; and &lt;code&gt;setCurrentUser()&lt;/code&gt; to the class of your plugin, helper, etc. In the getter (&lt;code&gt;getCurrentUser()&lt;/code&gt;) under the hood, it checks whether the current user is assigned and if not, it is obtained from the Application object. &lt;/p&gt;

&lt;h2&gt;
  
  
  How to use the CurrentUserTrait trait in Joomla?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Joomla\CMS\User\CurrentUserTrait&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Wtcategory&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;FieldsPlugin&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;SubscriberInterface&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;DatabaseAwareTrait&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;CurrentUserTrait&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;MyMethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getCurrentUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And thus, you can less monitor the relevance of the code base in this area, since the core functionality is used here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Joomla Community resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://joomla.org/" rel="noopener noreferrer"&gt;https://joomla.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Joomla Community chat in Mattermost (&lt;a href="https://docs.joomla.org/Mattermost" rel="noopener noreferrer"&gt;read more&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web-tolk.ru/en/dev" rel="noopener noreferrer"&gt;WebTolk Joomla extensions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>joomla</category>
      <category>php</category>
      <category>webdev</category>
      <category>development</category>
    </item>
  </channel>
</rss>
