Skip to content

Conversation

@robbiejackson
Copy link
Contributor

@robbiejackson robbiejackson commented Dec 8, 2025

User description

This is what I'm proposing to replace the "Joomla 4 and 5 Changes".

The new page on methods and arguments is for events with concrete classes only.

I think it's ok to copy this to Joomla 5.4 as well as having it on v6 versions; let me know if you disagree.

I've moved a couple of things to a "Plugin Advanced Features" page, and this is where we could put lazy loading when it's implemented.

For someone starting to learn about plugins the sequence of pages to read would then be:

  • how plugins work
  • methods and arguments
  • tutorial example
  • advanced features

I've also made some other smaller changes to remove links to the "Joomla 4 and 5 Changes" page and improve readability.

I'm also assuming I'll include this version of the tutorial code in the manual examples repo.


PR Type

Enhancement, Documentation


Description

  • Restructure plugin documentation by replacing "Joomla 4 and 5 Changes" page with focused "Plugin Methods and Arguments" page

  • Create new "Advanced Features" page for plugin priority and event propagation

  • Update tutorial plugin code to use concrete event classes instead of generic events

  • Improve plugin documentation organization and remove version-specific content


Diagram Walkthrough

flowchart LR
  A["Old Structure<br/>Joomla 4 and 5 Changes"] -->|Replace| B["New Structure<br/>Methods and Arguments"]
  B --> C["Plugin Methods<br/>and Arguments"]
  B --> D["Advanced Features"]
  E["Tutorial Code<br/>Generic Events"] -->|Update| F["Tutorial Code<br/>Concrete Events"]
  C --> G["Improved Learning<br/>Path"]
  D --> G
Loading

File Walkthrough

Relevant files
Documentation
7 files
advanced-features.md
New page documenting plugin priority and propagation         
+32/-0   
how-plugins-work.md
Add section headers and improve readability                           
+14/-0   
joomla-4-and-5-changes.md
Remove deprecated Joomla version comparison page                 
+0/-284 
methods-and-arguments.md
New comprehensive guide for plugin methods and event arguments
+298/-0 
content.md
Update reference to point to new methods-and-arguments page
+1/-1     
index.md
Remove outdated Joomla 4 and 5 version comparison text     
+0/-2     
installer.md
Update reference to point to new methods-and-arguments page
+1/-3     
Enhancement
2 files
basic-content-plugin.md
Update tutorial to use concrete event classes                       
+54/-47 
ajax-plugin.md
Simplify event result handling using concrete event classes
+2/-8     

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Dec 8, 2025

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
No audit logs: The newly added example code changes behavior and results without any accompanying
guidance or code for logging critical actions, but as this is documentation code, audit
logging may be intentionally out of scope.

Referred Code
    $article->text = $text;
}

public function addShortcodeSubtitle(AfterTitleEvent $event): void
{
    /* This function adds a subtitle to a page on the site front end:
     * "Processed for shortcodes" - if the page is an article
     * "Not processed for shortcodes" - if the page is a contact, etc.
     */

    if (!$this->getApplication()->isClient('site')) return;

    $context = $event->getContext();
    if ($context === "com_content.article" || $context === "com_content.featured") 
    {
        $event->addResult(Text::_('PLG_CONTENT_SHORTCODES_PROCESSED'));
    } else {
        $event->addResult(Text::_('PLG_CONTENT_SHORTCODES_NOT_PROCESSED'));
    }

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Missing handlers: Example handler methods lack explicit error handling and null/empty checks (e.g.,
accessing $article->text and configuration array) though this may be acceptable for
simplified documentation samples.

Referred Code
public function replaceShortcodes(ContentPrepareEvent $event): void
{
    /* This function processes the text of an article being presented on the site.
     * It replaces any text of the form "{configname}" (where configname is the name 
     * of a config parameter in configuration.php) with the value of the parameter.
     */

    // We used setApplication on our plugin instance inside services/provider.php to set the Application instance
    // Now we can retrieve it here using getApplication.
    // getApplication and setApplication are inherited from CMSPlugin
    $app = $this->getApplication();

    // The line below restricts the functionality to the front-end site (ie not admin/api/console job)
    // You may not want this, so you need to consider this in your own plugins
    if (!$app->isClient('site')) {
        return;
    }

    // Find out if this event relates to an article or something else (eg contact, user)
    $context = $event->getContext();
    if ($context !== "com_content.article" && $context !== "com_content.featured") return;


 ... (clipped 9 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Input validation: The example replaces shortcodes from configuration into article text without demonstrating
validation/sanitization or output escaping, which may be acceptable for instructional docs
but could be risky if copied verbatim.

Referred Code
// The line below restricts the functionality to the front-end site (ie not admin/api/console job)
// You may not want this, so you need to consider this in your own plugins
if (!$app->isClient('site')) {
    return;
}

// Find out if this event relates to an article or something else (eg contact, user)
$context = $event->getContext();
if ($context !== "com_content.article" && $context !== "com_content.featured") return;

// If we've reached here then it's an article - get the 'text' property
$article = $event->getItem();
$text = $article->text; // text of the article

$config = $app->getConfig()->toArray();  // config params as an array
    // (we can't do a foreach over the config params as a Registry because they're protected)

// the following is just code to replace {configname} with the parameter value

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Dec 8, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Retain backward compatibility documentation

Instead of deleting all documentation on backward compatibility for handling
GenericEvent versus concrete event classes, move this essential guidance to a
new, dedicated page. This information is vital for developers whose extensions
need to support various Joomla versions.

Examples:

docs/building-extensions/plugins/joomla-4-and-5-changes.md [1-284]
docs/building-extensions/plugins/basic-content-plugin.md [194-292]
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Event\Content\ContentPrepareEvent;
use Joomla\CMS\Event\Content\AfterTitleEvent;
use Joomla\Event\SubscriberInterface;
use Joomla\CMS\Language\Text;

class Shortcode extends CMSPlugin implements SubscriberInterface
{
    public static function getSubscribedEvents(): array
    {

 ... (clipped 89 lines)

Solution Walkthrough:

Before:

// docs/building-extensions/plugins/joomla-4-and-5-changes.md
# Joomla 4 and 5 Changes
...
**It's important to understand that the way you obtain the parameters ... and the way which you provide your return value is different depending on whether a GenericEvent or a concrete class is used.**
...
To return a value your plugin should use `$event->addResult($value)`, but you can check if this method exists by:
```php
use Joomla\CMS\Event\Result\ResultAwareInterface;
...
    if ($event instanceof ResultAwareInterface) {
        $event->addResult($value);
    } else {
        // use GenericEvent approach
    }

// docs/building-extensions/plugins/basic-content-plugin.md
// The tutorial plugin shows how to handle both event types.
public function addShortcodeSubtitle(Event $event) {
if ($event instanceof ResultAwareInterface) {
$event->addResult(...);
} else {
// handle GenericEvent
}
}




#### After:
```markdown
// docs/building-extensions/plugins/methods-and-arguments.md
// This file focuses on the modern approach with concrete events.
# Plugin Methods and Arguments
...
public function modifyContent(ContentPrepareEvent $event): void
{
    // ...
}
...
$event->addResult($value);

// docs/building-extensions/plugins/backward-compatibility.md (New File)
# Backward Compatibility
This page explains how to support multiple Joomla versions.
...
## Generic vs. Concrete Events
To handle both, check if the event is an instance of `ResultAwareInterface`:
```php
if ($event instanceof ResultAwareInterface) {
    $event->addResult($value);
} else {
    // use GenericEvent approach for older versions
}




<details><summary>Suggestion importance[1-10]: 9</summary>

__

Why: The suggestion correctly identifies that the PR completely removes crucial documentation for backward compatibility, which is essential for developers supporting multiple Joomla versions, and proposes a valid alternative.


</details></details></td><td align=center>High

</td></tr><tr><td rowspan=1>General</td>
<td>



<details><summary>Remove outdated backward-compatibility code</summary>

___

**Remove the backward-compatibility check for <code>ResultAwareInterface</code> and directly <br>use <code>$event->addResult($output)</code> to align with the PR's modernization goal.**

[docs/building-extensions/plugins/plugin-examples/ajax-plugin.md [179-185]](https://github.com/joomla/Manual/pull/562/files#diff-24998db8c6edc434324ad92c465a8166cd4e4cfd483c7216b8101eb638225cf8R179-R185)

```diff
-if ($event instanceof ResultAwareInterface) {
-    $event->addResult($output);
-} else {
-    $result = $event->getArgument('result') ?? [];
-    $result[] = $output;
-    $event->setArgument('result', $result);
-}
+$event->addResult($output);

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies and removes outdated backward-compatibility code, aligning the example with the PR's goal of modernizing the documentation and ensuring consistency across all examples.

Medium
  • Update

@HLeithner
Copy link
Member

Looks nice thanks, did only a quick look, maybe @Fedik could have a deeper look at it? thanks

@Fedik
Copy link
Member

Fedik commented Dec 8, 2025

I added a few comments. But in general it is good. Thanks!

@robbiejackson
Copy link
Contributor Author

I've fixed up the documents after the comments and duplicated to the other versions.

I reckon this is ready for merging, unless anyone has any other comments.

@Fedik
Copy link
Member

Fedik commented Dec 11, 2025

I added few comments.
Rest is looks good to me.

@robbiejackson robbiejackson merged commit e66a3fd into joomla:main Dec 11, 2025
2 checks passed
@robbiejackson robbiejackson deleted the redo-plugin-methods-for-v6 branch December 11, 2025 21:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants