├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── report-a-problem.md │ ├── request-for-new-content.md │ └── something-else.md ├── PULL_REQUEST_TEMPLATE.md ├── SECURITY.md ├── SUPPORT.md └── workflows │ └── deploy-to-personal.yml ├── .gitignore ├── .idea ├── .gitignore ├── .name ├── Joomla Extensions Development.iml ├── inspectionProfiles │ └── Project_Default.xml ├── jsLibraryMappings.xml ├── misc.xml ├── modules.xml ├── pandoc.xml ├── phing.xml ├── php.xml └── vcs.xml ├── LICENSE.md ├── README.md ├── assets └── JoomlaExtensionNamespace.png ├── joomla_extensions_development.xml └── sections ├── advice.xml ├── components.xml ├── concepts.xml ├── fdl.xml ├── gpl.xml ├── modules.xml ├── plugins.xml └── preface.xml /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | https://www.dionysopoulos.me/contact-me.html. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Welcome to the Joomla Extensions Development book's contributing guide 2 | 3 | Thank you for investing your time in contributing to my project! Any contribution you make will be reflected on [the HTML version of the book](https://www.dionysopoulos.me/book.html) and any releases I make in other formats. 4 | 5 | Read the [Code of Conduct](CODE_OF_CONDUCT.md) to keep our community approachable and respectable. 6 | 7 | In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR. 8 | 9 | Use the table of contents icon in the top left corner of this document to get to a specific section of this guide quickly. 10 | 11 | ## New contributor guide 12 | 13 | To get an overview of the project, read the [README](../README.md). 14 | 15 | ## Getting started 16 | 17 | There are several types of contributions possible for this project: 18 | 19 | 1. Making corrections on typos or inaccuracies you've spotted. You can either report these problems in an issue or make a Pull Request directly with your proposed changes. 20 | 2. Proposing areas of Joomla extension development which need to be covered. Please submit an issue with your suggestions. Kindly note that I am doing this on my ever-diminishing spare time, I might not be able to implement your suggestion in a timely manner (or at all). 21 | 3. Write a not yet written section. Please submit an issue first stating the section you want to write and your projected timeline. Once accepted, you can write the content and submit a Pull Request. 22 | 23 | ### Issues 24 | 25 | #### Create a new issue 26 | 27 | If you spot a problem with the docs, please search if an issue already exists. If a related issue doesn't exist, you can open a new issue. 28 | 29 | #### Solve an issue 30 | 31 | Scan through the [existing issues](https://github.com/nikosdion/joomla_extensions_development/issues) to find one that interests you. If you find an issue to work on, please let me know. Once I give you the go-ahead you can make your changes and open a Pull Request with your changes. 32 | 33 | ### Make Changes 34 | 35 | 1. Fork the repository. 36 | - Using GitHub Desktop: 37 | - [Getting started with GitHub Desktop](https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/getting-started-with-github-desktop) will guide you through setting up Desktop. 38 | - Once Desktop is set up, you can use it to [fork the repo](https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/cloning-and-forking-repositories-from-github-desktop)! 39 | 40 | - Using the command line: 41 | - [Fork the repo](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#fork-an-example-repository) so that you can make your changes without affecting the original project until you're ready to merge them. 42 | 43 | 2. Create a working branch and start with your changes! To edit the XML file easily you can use the free version of the [XMLMind DocBook Editor](https://www.xmlmind.com/xmleditor/docbook_editor.html) (Personal Edition 44 | License). This kind of use is permitted as this book is distributed under an Open Source license making it an open source project for the purposes of [XMLMind's Personal License](https://www.xmlmind.com/xmleditor/license_xxe_perso.html). 45 | 46 | ### Commit your update 47 | 48 | Commit the changes once you are happy with them. 49 | 50 | ### Pull Request 51 | 52 | When you're finished with the changes, create a pull request, also known as a PR. 53 | - Don't forget to [link PR to issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if you are solving one. 54 | - Enable the checkbox to [allow maintainer edits](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so the branch can be updated for a merge. 55 | Once you submit your PR, I will review your proposal. I may ask questions or request for additional information. 56 | - I may ask for changes to be made before a PR can be merged, either using [suggested changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request) or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch. 57 | - As you update your PR and apply changes, mark each conversation as [resolved](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations). 58 | - If you run into any merge issues, checkout this [git tutorial](https://github.com/skills/resolve-merge-conflicts) to help you resolve merge conflicts and other issues. 59 | 60 | ### Your PR is merged! 61 | 62 | Once your PR is merged, your contributions will be publicly visible on [the HTML version of the book](https://www.dionysopoulos.me/book.html) within 15' or less. -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://paypal.me/nicholasakeeba 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/report-a-problem.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Report a problem 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe what's wrong** 11 | A clear and concise description of what the problem is. Please do tell us the section where the problem is and/or give us a link to the range of lines where you've found a problem. 12 | 13 | **Reasoning** 14 | If you are not reporting something as simple as a blatant typo, please describe your reasoning as to why the existing documentation is problematic. 15 | 16 | **Suggestion** 17 | How would you propose that this issue is best addressed? 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/request-for-new-content.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Request for new content 3 | about: Suggest an idea for expanding the documentation 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your request related to something missing or something already present?** 11 | If it's about something already covered please tell us the section name or number. 12 | 13 | **Is your request about a problem you had developing a Joomla extension? If so, what?** 14 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 15 | 16 | **Describe the documentation you'd like to see** 17 | A clear and concise description of what you want to see added to the documentation. 18 | 19 | **Describe alternatives you've considered** 20 | A clear and concise description of other sections you've consulted and, if trying to address a problem writing a Joomla extensions, any alternative solutions you've considered. 21 | 22 | **Additional context** 23 | Add any other context about your request here. 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/something-else.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Something else 3 | about: Questions and offers for assistance not falling in any of the categories above 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | Please make sure that your request does NOT fall into one of the following categories: 11 | * Help with developing or improving your own extension. This is a documentation project, not a free code review endeavour. 12 | * Using a third party editor to edit the documentation. Please refer to its documentation. 13 | * Converting the documentation to a different format. If all else fails you can still read it online. 14 | 15 | Examples of valid issues: 16 | * Offering to translate the documentation 17 | * Making a financial contribution 18 | * Reusing parts of the content or other clarification on its licensing 19 | * Clarification enquiry for the code samples 20 | * Questions while writing new content or editing existing content 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Pull Request for Issue # . 2 | 3 | ### Summary of Changes 4 | 5 | The executive summary of what you have changed. Think of it as your PR's elevator pitch. 6 | 7 | ### Reasoning 8 | 9 | If this is not a fix for a blatant typo or a follow-up to an already submitted issue please tell me your reasoning for making this change. -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | Throughout this documentation I am trying to give tips and best practices for helping developers create and maintain **secure** Joomla extensions. 4 | 5 | If you have spotted something in the documentation, either the prose or the code samples, which might mislead someone into writing insecure code or is outright insecure please submit an issue using the “Something else” template. Please do try to explain the context of the security issue you found. 6 | 7 | **Do not use issues in this repository to report security issues for Joomla itself or for my software**. 8 | 9 | If you want to report a security issue in Joomla itself please consult [Joomla's security policy](https://github.com/joomla/joomla-cms/blob/4.2-dev/.github/SECURITY.md) for the best ways to get in touch with the Joomla Security Strike Team. I am not a part of that team. 10 | 11 | If you want to report a security issue in my software please use [my GPG key](https://www.dionysopoulos.me/images/files/pgp_keys.asc) to encrypt your email text and submit it to [my site's contact form](https://www.dionysopoulos.me/contact-me.html). -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | ## Support philosophy 2 | 3 | This is a documentation project. By definition, documentation exists to help people understand how to do something they are unfamiliar with, or jog their memory if it's been a while since they've done it. 4 | 5 | Documentation is ultimately an exercise in communication. It doesn't matter how well I, the documentation writer, understand the subject if I cannot convey my knowledge to you, the reader. While I've been writing documentation in a professional capacity since 2004, I will not claim to be perfect. To this end, I am willing and happy to discuss how I can best improve the documentation to convey my knowledge to you. 6 | 7 | That said, there are a few conditions and a certain etiquette to follow to make this kind of interaction pleasant for all involved parties. 8 | 9 | ### Be respectful 10 | 11 | Please remember that behind the screen and the keyboard there's a breathing, living human. Be respectful and kind in your interactions with me and with each other. 12 | 13 | ### We are all volunteers, we all have lives to live 14 | 15 | I am writing this documentation book on my own spare time, without any financial or other kind of reimbursement. I am doing this because I genuinely want to help the Joomla community and, well, because I like writing. 16 | 17 | I make a reasonable assumption that you are also here on your own spare time interacting with me and with one another because you, too, want to help the Joomla community. That's awesome and I thank you from the depths of my heart! 18 | 19 | Do keep in mind, though, that since we're all here on our own spare time there might be a few hours, days, weeks or even months when _life_ happens. During those times we may have limited or no availability. I don't expect you to drop everything to contribute to this repository and I expect you to have the same understanding when it comes to my and other people's time as well. 20 | 21 | ### This is not a free of charge code auditing service 22 | 23 | Please do not send me your code for review, even if you tell me that this is the code you wrote after reading the documentation I wrote. I cannot do a code review for you. 24 | 25 | Instead, do tell me which parts of the documentation you read and what you found unclear, confusing or misleading — and _why_. This will help me improve this book for you and everyone else reading it. 26 | 27 | ### We're here to teach _and_ learn 28 | 29 | Even though I am the one writing this documentation I do not claim to be an infallible expert in everything under the sun. 30 | 31 | At best, this documentation represents my subjective knowledge of how Joomla works and what I have done over the years to make my software more efficient and easier to maintain. This knowledge evolves on pretty much a daily basis. Writing this book I found out some wrongly held beliefs of mine and found, reported and fixed issues in Joomla itself — then came back to amend the book to reflect my accepted change in Joomla itself. 32 | 33 | It's possible that I may have claimed something which is not true or which is no longer true. There might be alternative ways to do things I have not considered or simply not existed as I was writing the documentation. I may be misremembering some old discussion or event in my side notes on Joomla's history. I may have made a silly typo. 34 | 35 | If you think I've made a mistake, please do tell me, so I can correct it. 36 | 37 | If you have a better way to do something than what I describe, please do tell me — and why it's better. Better ideas do deserve to be in the documentation. -------------------------------------------------------------------------------- /.github/workflows/deploy-to-personal.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to personal site 2 | on: [push] 3 | jobs: 4 | deployment: 5 | name: Deployment 6 | runs-on: ubuntu-latest 7 | environment: Dionysopoulos.me 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v2 11 | - name: Deploy over SSH 12 | uses: appleboy/scp-action@master 13 | with: 14 | host: ${{ secrets.SSH_HOST }} 15 | port: ${{ secrets.SSH_PORT }} 16 | username: ${{ secrets.SSH_USERNAME }} 17 | password: ${{ secrets.SSH_PASSWORD }} 18 | source: "joomla_extensions_development.xml,sections/advice.xml,sections/components.xml,sections/concepts.xml,sections/fdl.xml,sections/gpl.xml,sections/modules.xml,sections/plugins.xml,sections/preface.xml,sections/templates.xml,assets/JoomlaExtensionNamespace.png" 19 | target: ${{ secrets.SSH_PATH }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Temporary files 2 | /*.xml~ 3 | /sections/*.xml~ 4 | 5 | ### Temporary DocImport output 6 | /output 7 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | Joomla Extensions Development -------------------------------------------------------------------------------- /.idea/Joomla Extensions Development.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/pandoc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/phing.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $USER_HOME$/.composer/vendor/bin/phing 5 | 6 | -------------------------------------------------------------------------------- /.idea/php.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | 16 | 17 | 19 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ### GNU Free Documentation License 2 | 3 | Version 1.3, 3 November 2008 4 | 5 | Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, 6 | Inc. 7 | 8 | Everyone is permitted to copy and distribute verbatim copies of this 9 | license document, but changing it is not allowed. 10 | 11 | #### 0. PREAMBLE 12 | 13 | The purpose of this License is to make a manual, textbook, or other 14 | functional and useful document "free" in the sense of freedom: to 15 | assure everyone the effective freedom to copy and redistribute it, 16 | with or without modifying it, either commercially or noncommercially. 17 | Secondarily, this License preserves for the author and publisher a way 18 | to get credit for their work, while not being considered responsible 19 | for modifications made by others. 20 | 21 | This License is a kind of "copyleft", which means that derivative 22 | works of the document must themselves be free in the same sense. It 23 | complements the GNU General Public License, which is a copyleft 24 | license designed for free software. 25 | 26 | We have designed this License in order to use it for manuals for free 27 | software, because free software needs free documentation: a free 28 | program should come with manuals providing the same freedoms that the 29 | software does. But this License is not limited to software manuals; it 30 | can be used for any textual work, regardless of subject matter or 31 | whether it is published as a printed book. We recommend this License 32 | principally for works whose purpose is instruction or reference. 33 | 34 | #### 1. APPLICABILITY AND DEFINITIONS 35 | 36 | This License applies to any manual or other work, in any medium, that 37 | contains a notice placed by the copyright holder saying it can be 38 | distributed under the terms of this License. Such a notice grants a 39 | world-wide, royalty-free license, unlimited in duration, to use that 40 | work under the conditions stated herein. The "Document", below, refers 41 | to any such manual or work. Any member of the public is a licensee, 42 | and is addressed as "you". You accept the license if you copy, modify 43 | or distribute the work in a way requiring permission under copyright 44 | law. 45 | 46 | A "Modified Version" of the Document means any work containing the 47 | Document or a portion of it, either copied verbatim, or with 48 | modifications and/or translated into another language. 49 | 50 | A "Secondary Section" is a named appendix or a front-matter section of 51 | the Document that deals exclusively with the relationship of the 52 | publishers or authors of the Document to the Document's overall 53 | subject (or to related matters) and contains nothing that could fall 54 | directly within that overall subject. (Thus, if the Document is in 55 | part a textbook of mathematics, a Secondary Section may not explain 56 | any mathematics.) The relationship could be a matter of historical 57 | connection with the subject or with related matters, or of legal, 58 | commercial, philosophical, ethical or political position regarding 59 | them. 60 | 61 | The "Invariant Sections" are certain Secondary Sections whose titles 62 | are designated, as being those of Invariant Sections, in the notice 63 | that says that the Document is released under this License. If a 64 | section does not fit the above definition of Secondary then it is not 65 | allowed to be designated as Invariant. The Document may contain zero 66 | Invariant Sections. If the Document does not identify any Invariant 67 | Sections then there are none. 68 | 69 | The "Cover Texts" are certain short passages of text that are listed, 70 | as Front-Cover Texts or Back-Cover Texts, in the notice that says that 71 | the Document is released under this License. A Front-Cover Text may be 72 | at most 5 words, and a Back-Cover Text may be at most 25 words. 73 | 74 | A "Transparent" copy of the Document means a machine-readable copy, 75 | represented in a format whose specification is available to the 76 | general public, that is suitable for revising the document 77 | straightforwardly with generic text editors or (for images composed of 78 | pixels) generic paint programs or (for drawings) some widely available 79 | drawing editor, and that is suitable for input to text formatters or 80 | for automatic translation to a variety of formats suitable for input 81 | to text formatters. A copy made in an otherwise Transparent file 82 | format whose markup, or absence of markup, has been arranged to thwart 83 | or discourage subsequent modification by readers is not Transparent. 84 | An image format is not Transparent if used for any substantial amount 85 | of text. A copy that is not "Transparent" is called "Opaque". 86 | 87 | Examples of suitable formats for Transparent copies include plain 88 | ASCII without markup, Texinfo input format, LaTeX input format, SGML 89 | or XML using a publicly available DTD, and standard-conforming simple 90 | HTML, PostScript or PDF designed for human modification. Examples of 91 | transparent image formats include PNG, XCF and JPG. Opaque formats 92 | include proprietary formats that can be read and edited only by 93 | proprietary word processors, SGML or XML for which the DTD and/or 94 | processing tools are not generally available, and the 95 | machine-generated HTML, PostScript or PDF produced by some word 96 | processors for output purposes only. 97 | 98 | The "Title Page" means, for a printed book, the title page itself, 99 | plus such following pages as are needed to hold, legibly, the material 100 | this License requires to appear in the title page. For works in 101 | formats which do not have any title page as such, "Title Page" means 102 | the text near the most prominent appearance of the work's title, 103 | preceding the beginning of the body of the text. 104 | 105 | The "publisher" means any person or entity that distributes copies of 106 | the Document to the public. 107 | 108 | A section "Entitled XYZ" means a named subunit of the Document whose 109 | title either is precisely XYZ or contains XYZ in parentheses following 110 | text that translates XYZ in another language. (Here XYZ stands for a 111 | specific section name mentioned below, such as "Acknowledgements", 112 | "Dedications", "Endorsements", or "History".) To "Preserve the Title" 113 | of such a section when you modify the Document means that it remains a 114 | section "Entitled XYZ" according to this definition. 115 | 116 | The Document may include Warranty Disclaimers next to the notice which 117 | states that this License applies to the Document. These Warranty 118 | Disclaimers are considered to be included by reference in this 119 | License, but only as regards disclaiming warranties: any other 120 | implication that these Warranty Disclaimers may have is void and has 121 | no effect on the meaning of this License. 122 | 123 | #### 2. VERBATIM COPYING 124 | 125 | You may copy and distribute the Document in any medium, either 126 | commercially or noncommercially, provided that this License, the 127 | copyright notices, and the license notice saying this License applies 128 | to the Document are reproduced in all copies, and that you add no 129 | other conditions whatsoever to those of this License. You may not use 130 | technical measures to obstruct or control the reading or further 131 | copying of the copies you make or distribute. However, you may accept 132 | compensation in exchange for copies. If you distribute a large enough 133 | number of copies you must also follow the conditions in section 3. 134 | 135 | You may also lend copies, under the same conditions stated above, and 136 | you may publicly display copies. 137 | 138 | #### 3. COPYING IN QUANTITY 139 | 140 | If you publish printed copies (or copies in media that commonly have 141 | printed covers) of the Document, numbering more than 100, and the 142 | Document's license notice requires Cover Texts, you must enclose the 143 | copies in covers that carry, clearly and legibly, all these Cover 144 | Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on 145 | the back cover. Both covers must also clearly and legibly identify you 146 | as the publisher of these copies. The front cover must present the 147 | full title with all words of the title equally prominent and visible. 148 | You may add other material on the covers in addition. Copying with 149 | changes limited to the covers, as long as they preserve the title of 150 | the Document and satisfy these conditions, can be treated as verbatim 151 | copying in other respects. 152 | 153 | If the required texts for either cover are too voluminous to fit 154 | legibly, you should put the first ones listed (as many as fit 155 | reasonably) on the actual cover, and continue the rest onto adjacent 156 | pages. 157 | 158 | If you publish or distribute Opaque copies of the Document numbering 159 | more than 100, you must either include a machine-readable Transparent 160 | copy along with each Opaque copy, or state in or with each Opaque copy 161 | a computer-network location from which the general network-using 162 | public has access to download using public-standard network protocols 163 | a complete Transparent copy of the Document, free of added material. 164 | If you use the latter option, you must take reasonably prudent steps, 165 | when you begin distribution of Opaque copies in quantity, to ensure 166 | that this Transparent copy will remain thus accessible at the stated 167 | location until at least one year after the last time you distribute an 168 | Opaque copy (directly or through your agents or retailers) of that 169 | edition to the public. 170 | 171 | It is requested, but not required, that you contact the authors of the 172 | Document well before redistributing any large number of copies, to 173 | give them a chance to provide you with an updated version of the 174 | Document. 175 | 176 | #### 4. MODIFICATIONS 177 | 178 | You may copy and distribute a Modified Version of the Document under 179 | the conditions of sections 2 and 3 above, provided that you release 180 | the Modified Version under precisely this License, with the Modified 181 | Version filling the role of the Document, thus licensing distribution 182 | and modification of the Modified Version to whoever possesses a copy 183 | of it. In addition, you must do these things in the Modified Version: 184 | 185 | - A. Use in the Title Page (and on the covers, if any) a title 186 | distinct from that of the Document, and from those of previous 187 | versions (which should, if there were any, be listed in the 188 | History section of the Document). You may use the same title as a 189 | previous version if the original publisher of that version 190 | gives permission. 191 | - B. List on the Title Page, as authors, one or more persons or 192 | entities responsible for authorship of the modifications in the 193 | Modified Version, together with at least five of the principal 194 | authors of the Document (all of its principal authors, if it has 195 | fewer than five), unless they release you from this requirement. 196 | - C. State on the Title page the name of the publisher of the 197 | Modified Version, as the publisher. 198 | - D. Preserve all the copyright notices of the Document. 199 | - E. Add an appropriate copyright notice for your modifications 200 | adjacent to the other copyright notices. 201 | - F. Include, immediately after the copyright notices, a license 202 | notice giving the public permission to use the Modified Version 203 | under the terms of this License, in the form shown in the 204 | Addendum below. 205 | - G. Preserve in that license notice the full lists of Invariant 206 | Sections and required Cover Texts given in the Document's 207 | license notice. 208 | - H. Include an unaltered copy of this License. 209 | - I. Preserve the section Entitled "History", Preserve its Title, 210 | and add to it an item stating at least the title, year, new 211 | authors, and publisher of the Modified Version as given on the 212 | Title Page. If there is no section Entitled "History" in the 213 | Document, create one stating the title, year, authors, and 214 | publisher of the Document as given on its Title Page, then add an 215 | item describing the Modified Version as stated in the 216 | previous sentence. 217 | - J. Preserve the network location, if any, given in the Document 218 | for public access to a Transparent copy of the Document, and 219 | likewise the network locations given in the Document for previous 220 | versions it was based on. These may be placed in the "History" 221 | section. You may omit a network location for a work that was 222 | published at least four years before the Document itself, or if 223 | the original publisher of the version it refers to 224 | gives permission. 225 | - K. For any section Entitled "Acknowledgements" or "Dedications", 226 | Preserve the Title of the section, and preserve in the section all 227 | the substance and tone of each of the contributor acknowledgements 228 | and/or dedications given therein. 229 | - L. Preserve all the Invariant Sections of the Document, unaltered 230 | in their text and in their titles. Section numbers or the 231 | equivalent are not considered part of the section titles. 232 | - M. Delete any section Entitled "Endorsements". Such a section may 233 | not be included in the Modified Version. 234 | - N. Do not retitle any existing section to be Entitled 235 | "Endorsements" or to conflict in title with any Invariant Section. 236 | - O. Preserve any Warranty Disclaimers. 237 | 238 | If the Modified Version includes new front-matter sections or 239 | appendices that qualify as Secondary Sections and contain no material 240 | copied from the Document, you may at your option designate some or all 241 | of these sections as invariant. To do this, add their titles to the 242 | list of Invariant Sections in the Modified Version's license notice. 243 | These titles must be distinct from any other section titles. 244 | 245 | You may add a section Entitled "Endorsements", provided it contains 246 | nothing but endorsements of your Modified Version by various 247 | parties—for example, statements of peer review or that the text has 248 | been approved by an organization as the authoritative definition of a 249 | standard. 250 | 251 | You may add a passage of up to five words as a Front-Cover Text, and a 252 | passage of up to 25 words as a Back-Cover Text, to the end of the list 253 | of Cover Texts in the Modified Version. Only one passage of 254 | Front-Cover Text and one of Back-Cover Text may be added by (or 255 | through arrangements made by) any one entity. If the Document already 256 | includes a cover text for the same cover, previously added by you or 257 | by arrangement made by the same entity you are acting on behalf of, 258 | you may not add another; but you may replace the old one, on explicit 259 | permission from the previous publisher that added the old one. 260 | 261 | The author(s) and publisher(s) of the Document do not by this License 262 | give permission to use their names for publicity for or to assert or 263 | imply endorsement of any Modified Version. 264 | 265 | #### 5. COMBINING DOCUMENTS 266 | 267 | You may combine the Document with other documents released under this 268 | License, under the terms defined in section 4 above for modified 269 | versions, provided that you include in the combination all of the 270 | Invariant Sections of all of the original documents, unmodified, and 271 | list them all as Invariant Sections of your combined work in its 272 | license notice, and that you preserve all their Warranty Disclaimers. 273 | 274 | The combined work need only contain one copy of this License, and 275 | multiple identical Invariant Sections may be replaced with a single 276 | copy. If there are multiple Invariant Sections with the same name but 277 | different contents, make the title of each such section unique by 278 | adding at the end of it, in parentheses, the name of the original 279 | author or publisher of that section if known, or else a unique number. 280 | Make the same adjustment to the section titles in the list of 281 | Invariant Sections in the license notice of the combined work. 282 | 283 | In the combination, you must combine any sections Entitled "History" 284 | in the various original documents, forming one section Entitled 285 | "History"; likewise combine any sections Entitled "Acknowledgements", 286 | and any sections Entitled "Dedications". You must delete all sections 287 | Entitled "Endorsements". 288 | 289 | #### 6. COLLECTIONS OF DOCUMENTS 290 | 291 | You may make a collection consisting of the Document and other 292 | documents released under this License, and replace the individual 293 | copies of this License in the various documents with a single copy 294 | that is included in the collection, provided that you follow the rules 295 | of this License for verbatim copying of each of the documents in all 296 | other respects. 297 | 298 | You may extract a single document from such a collection, and 299 | distribute it individually under this License, provided you insert a 300 | copy of this License into the extracted document, and follow this 301 | License in all other respects regarding verbatim copying of that 302 | document. 303 | 304 | #### 7. AGGREGATION WITH INDEPENDENT WORKS 305 | 306 | A compilation of the Document or its derivatives with other separate 307 | and independent documents or works, in or on a volume of a storage or 308 | distribution medium, is called an "aggregate" if the copyright 309 | resulting from the compilation is not used to limit the legal rights 310 | of the compilation's users beyond what the individual works permit. 311 | When the Document is included in an aggregate, this License does not 312 | apply to the other works in the aggregate which are not themselves 313 | derivative works of the Document. 314 | 315 | If the Cover Text requirement of section 3 is applicable to these 316 | copies of the Document, then if the Document is less than one half of 317 | the entire aggregate, the Document's Cover Texts may be placed on 318 | covers that bracket the Document within the aggregate, or the 319 | electronic equivalent of covers if the Document is in electronic form. 320 | Otherwise they must appear on printed covers that bracket the whole 321 | aggregate. 322 | 323 | #### 8. TRANSLATION 324 | 325 | Translation is considered a kind of modification, so you may 326 | distribute translations of the Document under the terms of section 4. 327 | Replacing Invariant Sections with translations requires special 328 | permission from their copyright holders, but you may include 329 | translations of some or all Invariant Sections in addition to the 330 | original versions of these Invariant Sections. You may include a 331 | translation of this License, and all the license notices in the 332 | Document, and any Warranty Disclaimers, provided that you also include 333 | the original English version of this License and the original versions 334 | of those notices and disclaimers. In case of a disagreement between 335 | the translation and the original version of this License or a notice 336 | or disclaimer, the original version will prevail. 337 | 338 | If a section in the Document is Entitled "Acknowledgements", 339 | "Dedications", or "History", the requirement (section 4) to Preserve 340 | its Title (section 1) will typically require changing the actual 341 | title. 342 | 343 | #### 9. TERMINATION 344 | 345 | You may not copy, modify, sublicense, or distribute the Document 346 | except as expressly provided under this License. Any attempt otherwise 347 | to copy, modify, sublicense, or distribute it is void, and will 348 | automatically terminate your rights under this License. 349 | 350 | However, if you cease all violation of this License, then your license 351 | from a particular copyright holder is reinstated (a) provisionally, 352 | unless and until the copyright holder explicitly and finally 353 | terminates your license, and (b) permanently, if the copyright holder 354 | fails to notify you of the violation by some reasonable means prior to 355 | 60 days after the cessation. 356 | 357 | Moreover, your license from a particular copyright holder is 358 | reinstated permanently if the copyright holder notifies you of the 359 | violation by some reasonable means, this is the first time you have 360 | received notice of violation of this License (for any work) from that 361 | copyright holder, and you cure the violation prior to 30 days after 362 | your receipt of the notice. 363 | 364 | Termination of your rights under this section does not terminate the 365 | licenses of parties who have received copies or rights from you under 366 | this License. If your rights have been terminated and not permanently 367 | reinstated, receipt of a copy of some or all of the same material does 368 | not give you any rights to use it. 369 | 370 | #### 10. FUTURE REVISIONS OF THIS LICENSE 371 | 372 | The Free Software Foundation may publish new, revised versions of the 373 | GNU Free Documentation License from time to time. Such new versions 374 | will be similar in spirit to the present version, but may differ in 375 | detail to address new problems or concerns. See 376 | . 377 | 378 | Each version of the License is given a distinguishing version number. 379 | If the Document specifies that a particular numbered version of this 380 | License "or any later version" applies to it, you have the option of 381 | following the terms and conditions either of that specified version or 382 | of any later version that has been published (not as a draft) by the 383 | Free Software Foundation. If the Document does not specify a version 384 | number of this License, you may choose any version ever published (not 385 | as a draft) by the Free Software Foundation. If the Document specifies 386 | that a proxy can decide which future versions of this License can be 387 | used, that proxy's public statement of acceptance of a version 388 | permanently authorizes you to choose that version for the Document. 389 | 390 | #### 11. RELICENSING 391 | 392 | "Massive Multiauthor Collaboration Site" (or "MMC Site") means any 393 | World Wide Web server that publishes copyrightable works and also 394 | provides prominent facilities for anybody to edit those works. A 395 | public wiki that anybody can edit is an example of such a server. A 396 | "Massive Multiauthor Collaboration" (or "MMC") contained in the site 397 | means any set of copyrightable works thus published on the MMC site. 398 | 399 | "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 400 | license published by Creative Commons Corporation, a not-for-profit 401 | corporation with a principal place of business in San Francisco, 402 | California, as well as future copyleft versions of that license 403 | published by that same organization. 404 | 405 | "Incorporate" means to publish or republish a Document, in whole or in 406 | part, as part of another Document. 407 | 408 | An MMC is "eligible for relicensing" if it is licensed under this 409 | License, and if all works that were first published under this License 410 | somewhere other than this MMC, and subsequently incorporated in whole 411 | or in part into the MMC, (1) had no cover texts or invariant sections, 412 | and (2) were thus incorporated prior to November 1, 2008. 413 | 414 | The operator of an MMC Site may republish an MMC contained in the site 415 | under CC-BY-SA on the same site at any time before August 1, 2009, 416 | provided the MMC is eligible for relicensing. 417 | 418 | ### ADDENDUM: How to use this License for your documents 419 | 420 | To use this License in a document you have written, include a copy of 421 | the License in the document and put the following copyright and 422 | license notices just after the title page: 423 | 424 | Copyright (C) YEAR YOUR NAME. 425 | Permission is granted to copy, distribute and/or modify this document 426 | under the terms of the GNU Free Documentation License, Version 1.3 427 | or any later version published by the Free Software Foundation; 428 | with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. 429 | A copy of the license is included in the section entitled "GNU 430 | Free Documentation License". 431 | 432 | If you have Invariant Sections, Front-Cover Texts and Back-Cover 433 | Texts, replace the "with … Texts." line with this: 434 | 435 | with the Invariant Sections being LIST THEIR TITLES, with the 436 | Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. 437 | 438 | If you have Invariant Sections without Cover Texts, or some other 439 | combination of the three, merge those two alternatives to suit the 440 | situation. 441 | 442 | If your document contains nontrivial examples of program code, we 443 | recommend releasing these examples in parallel under your choice of 444 | free software license, such as the GNU General Public License, to 445 | permit their use in free software. 446 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Joomla Extensions Development 2 | 3 | **The missing Joomla reference for extension developers** 4 | 5 | Copyright ©2022-2024 Nikolaos Dionysopoulos 6 | 7 | Permission is granted to copy, distribute and/or modify this document under the terms of the [GNU Free Documentation License](LICENSE.md), Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". 8 | 9 | ## WORK IN PROGRESS 10 | 11 | I am currently in the process of writing this book. Many things are missing, even more need refining. 12 | 13 | Please keep in mind that I am writing this book on my own time, without any kind of funding, based on my own experiences developing software for Joomla, _just for the love of the community_. Please be kind. 14 | 15 | ## How to read this book 16 | 17 | An [HTML version of the book](https://www.dionysopoulos.me/book.html) can be found on my personal site. 18 | 19 | _The book on the site is kept automatically up-to-date._ Whenever there is a Git push to this repository —manual or by merging a Pull Request— a GitHub Action deploys the DocBook XML source documents to my site. A CRON job on my site runs every 10', checking if the file has changed. If it's changed since the last run, [Akeeba DocImport](https://github.com/akeeba/docimport) converts the XML book into HTML and publishes the updated articles. Automation! Mmm! 20 | 21 | ## “Developing” the book 22 | 23 | ### Editing the source 24 | 25 | The normative source format of this book is DocBook XML version 5+. You can find it in the `joomla_extensions_development.xml` file in this repository. 26 | 27 | This file is the “main document”. It has the book metadata and a bunch of [XInclude](https://en.wikipedia.org/wiki/XInclude) statements pulling in the various [chapters](sections) of the document, each one stored as its own, editable file in the `sections` folder. 28 | 29 | _Pro tip_: If you want to edit the XML file easily you can use the free version of the [XMLMind DocBook Editor](https://www.xmlmind.com/xmleditor/docbook_editor.html) (Personal Edition License). This kind of use is permitted as this book is distributed under an Open Source license making it an open source project for the purposes of [XMLMind's Personal License](https://www.xmlmind.com/xmleditor/license_xxe_perso.html). Remember that the sections in the main document will appear as non-editable. You will need to edit each individual chapter file separately. 30 | 31 | ### Proposing changes 32 | 33 | If you want to propose changes to the book please submit an issue or make Pull Request against the DocBook XML document. Make sure to check the [contribution guide](.github/CONTRIBUTING.md) first. 34 | 35 | ### Compiling the book to other formats 36 | 37 | The book can be converted to GitHub-flavored Markdown and EPUB formats using the [DocBook XSL](https://github.com/docbook/xslt10-stylesheets/releases) stylesheets and `xsltproc` from the [libxslt](http://www.xmlsoft.org/libxslt/index.html) project. 38 | 39 | You can install `libxslt` on Debian-based Linux distributions with 40 | ```bash 41 | sudo apt-get install libxslt-dev 42 | ``` 43 | On Ubuntu you can alternatively use Snap with 44 | ```bash 45 | sudo snap install libxslt 46 | ``` 47 | On macOS you can use the [HomeBrew](https://brew.sh) package manager to install `libxslt` with 48 | ```bash 49 | brew install libxslt 50 | ``` 51 | On Windows you can use the [Chocolatey](https://chocolatey.org) package manager to install `xsltproc` with 52 | ```powershell 53 | choco install xsltproc 54 | ``` 55 | 56 | Assuming that `xsltproc` is in your path and the [DocBooc XSL stylesheets](https://github.com/docbook/xslt10-stylesheets) installed in `/opt/docbook-xsl` you can convert the DocBook XML sources to chunked HTML under the directory `/var/www/html/jextdev` with: 57 | 58 | ```bash 59 | xsltproc --nonet --xinclude --novalid \ 60 | --stringparam body.start.indent 0 \ 61 | --stringparam variablelist.term.break.after 1 \ 62 | --stringparam variablelist.term.separator "" \ 63 | --stringparam variablelist.max.termlength 12 \ 64 | --stringparam section.autolabel 1 \ 65 | --stringparam toc.section.depth 5 \ 66 | --stringparam base.dir /var/www/html/jextdev \ 67 | /opt/docbook-xsl/html/chunkfast.xsl \ 68 | joomla_extensions_development.xml 69 | ``` 70 | 71 | Note 1: do not try to convert the book to HTML, PDF, or ePUB with the Personal Edition of XMLMind DocBook Editor. It is designed to duplicate letters in random words of the output document (the converter is just a preview of their commercial offering). 72 | 73 | Note 2: conversion to PDF involves converting the DocBook XML sources to XML:FO and using Apache FOP to convert to PDF. Apache FOP is no longer developed, therefore no effort was spent to optimise the book for PDF export. As a result there are text overflow issues in the numerous code samples in the book which will not be fixed. 74 | 75 | Note 3: this repository is not the right place to ask for help about libxslt tools or the DocBook XSL Stylesheets. You're advised to consult [the documentation of DocBook XSL Stylesheets](http://www.sagehill.net/docbookxsl/) and [the man page of `xsltproc`](https://gnome.pages.gitlab.gnome.org/libxslt/xsltproc.html) 76 | -------------------------------------------------------------------------------- /assets/JoomlaExtensionNamespace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nikosdion/joomla_extensions_development/cede9f6d5f3f1489283fa3a27e9d5933278ac14a/assets/JoomlaExtensionNamespace.png -------------------------------------------------------------------------------- /joomla_extensions_development.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 19 | 20 | Joomla Extensions Development 21 | 22 | The missing Joomla reference for 23 | extension developers 24 | 25 | 26 | NicholasK.Dionysopoulos 27 | 28 | 29 | Nicholas is a software developer, mostly known for his work in 30 | Akeeba Backup and Admin Tools. He's been writing Joomla extensions 31 | since 2006 — and software in general for another decade, since his 32 | middle school years. He is a regular contributor to the Joomla 33 | project. When he's not writing code he enjoys writing documentation to 34 | spread the knowledge and the Joomla love. He lives in Greece with his 35 | wife, daughter and their two cats. 36 | 37 | 38 | 39 | January 2024 40 | 41 | 42 | 2022-2024 43 | 44 | Nikolaos Dionysopoulos 45 | 46 | 47 | 48 | Developing Joomla extensions is fun and fulfilling. However, its 49 | API evolves to better suit the changing times and PHP best practices. 50 | When Joomla 4 came out with its richer, brand new API there was no 51 | documentation to tell developers how to update and keep developing their 52 | extensions. Moreover, over a decade of API stagnation and lack of 53 | documentation led developers to complacency, bad code, and 54 | unmaintainable code. This book aims to distill my experience writing 55 | Joomla software since 2006 and includes some useful background on how 56 | some features were decided, how they are meant to be used, and where 57 | they fit in the larger picture of writing efficient, maintainable code. 58 | This is neither a tutorial nor a reference book. It's more of a 59 | practical guide through the Joomla extensions development API. 60 | 61 | This book covers development of Joomla! extensions under Joomla 62 | versions 4 and 5. 63 | 64 | 65 | 66 | Permission is granted to copy, distribute and/or modify this 67 | document under the terms of the GNU Free Documentation License, Version 68 | 1.3 or any later version published by the Free Software Foundation; with 69 | no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A 70 | copy of the license is included in the section entitled "GNU Free Documentation License". 72 | 73 | 74 | 75 | This work is not affiliated with or endorsed by the Joomla! 76 | Project. It is not supported or warranted by the Joomla! Project or Open 77 | Source Matters. The Joomla! logo is used under a limited license granted 78 | by Open Source Matters, the trademark holder in the United States and 79 | other countries. 80 | 81 | 82 | 83 | All code found in the code samples in this book is free software; 84 | you can redistribute it and/or modify it under the terms of the GNU 85 | General Public License as published by the Free Software Foundation; 86 | either version 2 of the License, or (at your option) any later 87 | version. 88 | 89 | This sample program code is distributed in the hope that it will 90 | be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 91 | of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 93 | 94 | You should have received a copy of the GNU General Public License 95 | along with this sample program code; if not, write to the Free Software 96 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 97 | USA 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /sections/concepts.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 19 | Basic concepts 20 | 21 | As mentioned in the introduction, Joomla 4 introduced a lot 23 | of new features. Some of these features introduce new fundamental concepts 24 | or refine existing ones. Before delving deeper into Joomla extension 25 | development let's take a look at these basic concepts to make sure we are 26 | all on the same page. 27 | 28 |
29 | Namespaces 30 | 31 | The single most defining change in Joomla 4 is that Joomla embraces 32 | PHP 34 | namespaces everywhere: core, core extensions, third party 35 | extensions and everything in between. 36 | 37 | The core 38 | 39 | The work on namespacing core Joomla API classes had started since 40 | Joomla 3.3. If you have not updated your code the last few years you may 41 | have found that it no longer works on Joomla 4. Do not despair! The vast 42 | majority of issues comes from your using outdated, non-namespaced versions 43 | of core classes in your code. Replacing them with their namespaced 44 | versions will let most Joomla 3–only extensions to run well enough in 45 | Joomla 4 for a migration to be practical. 46 | 47 | I have collected the old, non-namespaced core classes and the new, 48 | namespaced names of them along with the Joomla version the namespaced 49 | versions appeared and the Joomla version the non-namespaced versions are 50 | or will be removed in my 52 | Joomla Type Hints repository. The repository also includes Rector configurations which 54 | allow you to do most of the heavy lifting using an automated tool. For 55 | everything else you need some good old search and replace across your 56 | source trees. 57 | 58 | The extensions 59 | 60 | The story of Joomla 4 began on the last day of May 2015 in Prague, 61 | Czech Republic at a round table discussion about the future of Joomla. A 62 | dozen or so leadership members, core contributors and third party 63 | developers sat down to figure out why Joomla “sucks” and how to improve 64 | it. 65 | 66 | Beyond the user-facing issues, we found out that the core MVC and 67 | architecture were extremely dated. The core MVC started being developed in 68 | 2005 and made its first appearance in 2007, with Joomla 1.5. It had not 69 | changed much, despite some moderate improvements in Joomla 1.6 which was 70 | released in 2010 (e.g. XML Forms) and a few disparate things added here 71 | and there (e.g. Tags in 3.2, Layouts in 3.4 and so on). You could not 72 | reference frontend code from the backend or vice-versa. For third party 73 | extensions this was an annoyance which led to duplicated code and bugs. 74 | For using core code, like creating articles the right 75 | way using com_content's Article model, it was 76 | nearly impossible: if you tried doing that on a page which had already 77 | loaded the front-end ContentModelArticle class you could no longer load 78 | the same-named but entirely differently operating backend class. 79 | 80 | The way to solve that would be to namespace the 81 | extensions' code. A com_example extension could have the namespace prefix 82 | \MyCompany\Component\Example\Administrator for its backend classes and 83 | \MyCompany\Company\Example\Site for its frontend classes. This way you 84 | could have something like: 85 | 86 | namespace \MyCompany\Component\Example\Site\Model; 87 | 88 | class ItemModel extends \MyCompany\Component\Example\Administrator\Model\ItemModel 89 | { 90 | // ... 91 | } 92 | 93 | By being able to extend classes across application sides you would 94 | finally be able to get rid of duplicate code and obliterate bugs coming 95 | from that bad practice. 96 | 97 | By following the PSR-4 standard we 99 | could also have a very efficient autoloader which allows us to load any 100 | extension's classes from anywhere, without having to know where on the 101 | filesystem the class file lives and without having to use the ugly static 102 | methods of the core MVC classes (which, by the way, would NOT work 103 | predictably across extensions because of their dependence on the 104 | JPATH_COMPONENT_ADMINISTRATOR and 105 | JPATH_COMPONENT constants which cannot, of course, be 106 | redefined). 107 | 108 | Each extension's namespace is declared in the XML manifest of the 109 | extension using a new XML element under the <extension> 110 | root element: 111 | 112 | <namespace path="src">MyCompany\Component\Example</namespace> 113 | 114 | The path attribute tells Joomla which subdirectory of 115 | your extension holds the PSR-4 of your extension's PHP files. It is best 116 | practice to name it src but you don't have 117 | to. In the rest of this section I assume you are using 118 | src. 119 | 120 | The text inside the XML element, 121 | MyCompany\Component\Example in our example, is the namespace 122 | prefix you will be using. 123 | 124 | Here is how namespace prefixes work for Joomla extensions: 125 | 126 | 127 | 128 | All extensions start with a vendor 129 | namespace prefix. For Joomla's core extensions that is 130 | "\Joomla". For your custom extension you can use your own namespace, 131 | like your company name. This vendor namespace prefix can have multiple 132 | segments, for instance 133 | \Acme\Development\Utilities. 134 | 135 | 136 | 137 | After the vendor namespace prefix there is a namespace segment 138 | to indicate the extension type: 139 | \Component, \Module or 140 | \Plugin. 141 | 142 | 143 | 144 | When the extension type is a component or a module it is 145 | followed by: 146 | 147 | a namespace segment with the extension name (without the 149 | com_ or mod_ prefix) 150 | 151 | 152 | 153 | and after that a segment with the application type: 155 | \Administrator, \Site or 156 | \Api. 157 | 158 | 159 | 160 | 161 | 162 | When the extension type is a plugin it is followed by: 163 | 164 | 165 | 166 | a namespace segment with the plugin 167 | type, for instance \Content, \Finder or \System 168 | 169 | 170 | 171 | and after that a segment with the extension name (without the 173 | plg_ prefix) 174 | 175 | 176 | 177 | 178 | 179 | Joomla's extension namespace prefixes as a railroad diagram: 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | Examples across different types of extensions: 188 | 189 | 190 | 191 | Component, frontend. The 192 | component com_example by Acme, Inc could have a namespace 193 | prefix of \Acme\Component\Example set up in its XML 194 | manifest. In this case its frontend classes MUST be under the 195 | namespace \Acme\Component\Example\Site. The folder 196 | components/com_example/src is the root of the 197 | \Acme\Component\Example\Site namespace. 198 | 199 | 200 | 201 | Component, backend. The same 202 | component com_example by Acme, Inc which has a namespace 203 | prefix of \Acme\Component\Example. In this case its 204 | backend classes MUST be under the namespace 205 | \Acme\Component\Example\Administrator. The folder 206 | administrator/components/com_example/src is the 207 | root of the \Acme\Component\Example\Administrator 208 | namespace. 209 | 210 | 211 | 212 | Component, API application. The 213 | API application is the third type of Joomla application (the other two 214 | being Site the frontend, and Administrator the backend). We'll talk 215 | about it later in this book. Let's say 216 | we have the component com_example by Acme, Inc which has 217 | a namespace prefix of \Acme\Component\Example. In this 218 | case its API application classes MUST be under the namespace 219 | \Acme\Component\Example\Api. The folder 220 | api/components/com_example/src is the root of the 221 | \Acme\Component\Example\Api namespace. 222 | 223 | 224 | 225 | Module, frontend. The module 226 | mod_example by Acme, Inc could have a namespace prefix of 227 | \Acme\Module\Example set up in its XML manifest. If it is 228 | a frontend module the namespace will then be 229 | \Acme\Module\Example\Site and the folder 230 | modules/mod_example/src is the root of that 231 | namespace. 232 | 233 | 234 | 235 | Module, backend. If that module 236 | mod_example by Acme, Inc would be a backend module, with 237 | the same namespace prefix \Acme\Module\Example declared 238 | in its XML manifest, the namespace will then be 239 | \Acme\Module\Example\Administrator. The folder 240 | administrator/modules/mod_example/src is the root 241 | of the \Acme\Module\Example\Administrator 242 | namespace. 243 | 244 | 245 | 246 | Plugin. The plugin 247 | plg_system_example by Acme, Inc could have a namespace 248 | prefix of \Acme\Plugin\System\Example set up in its XML 249 | manifest. The folder plugins/system/example/src 250 | is the root of that \Acme\Plugin\System\Example 251 | namespace. 252 | 253 | 254 | 255 | Template. Well, Joomla does NOT 256 | register a namespace for templates. You are encouraged to use 257 | namespaces for any template-specific code (you certainly have some 258 | helpers, don't you?) BUT Joomla won't facilitate you with any 259 | autoloading. You will have to register your template's namespace 260 | directly with the JLoader::registerPrefix method. It is a 261 | good practice putting your namespaced PHP files in the 262 | src directory and use the namespace 263 | \MyCompany\Template\Site\Something for frontend templates 264 | and \MyCompany\Template\Administrator\Something for 265 | backend templates. Please note that there is no real guidance for the 266 | template names BUT we can infer what any future change adding 267 | namespace support to templates will most likely be based on how 268 | modules are namespaced and Joomla trying to have a modicum of 269 | consistency. 270 | 271 | 272 | 273 | How to choose a namespace for your extension 274 | 275 | Namespaces have for two primary reasons of existence: 276 | 277 | 278 | 279 | Uniqueness. Each of the 280 | extensions installed on the same site in different directories must 281 | have a unique namespace prefix which is not a subset or a superset of 282 | the namespace prefix of another extension and does not clash (be 283 | identical to) the namespace prefix of another extension. 284 | 285 | 286 | 287 | Identifiability. Namespaces of 288 | Joomla extensions should make it fairly obvious which extension they 289 | belong to when read by people with little to no PHP coding 290 | experience. 291 | 292 | 293 | 294 | Let's see some bad examples first. 295 | 296 | 297 | 298 | A component with the namespace prefix 299 | Acme\Component\Example and a plugin with the 300 | prefix Acme\Component\Example\Plugin\System. 301 | This is not correctly the rules set out above and violates both 302 | reasons for having a namespace: the namespace prefixes are not unique 303 | (the plugin's prefix is a subset of the component's prefix) and it's 304 | hard to understand which extension they refer to. 305 | 306 | 307 | 308 | A component released by Yoyodyne Corporation with the namespace 309 | prefix Acme\Component\Example. This violates 310 | the second rule as a casual bystander would assume that the component 311 | was written by a company called Acme, not Yoyodyne. 312 | 313 | 314 | 315 | A system plugin called foobar with the namespace 316 | Acme\Plugin\System\Foo. Again, it violates both 317 | reasons as it's neither unique (plg_system_foo could use 318 | the same namespace!) and does not help people identify the plugin in 319 | question. 320 | 321 | 322 | 323 | Based on the bad examples it's easy to understand what a 324 | good namespace is. 325 | 326 | A good namespace is generally constructed as follows: 327 | 328 | 329 | 330 | The company name, as commonly referred to in marketing and 331 | documentation. For example Joomla (the project name commonly used), 332 | not OpenSourceMattersInc (the full name of the non-profit legal entity 333 | which owns the Joomla trademark). 334 | 335 | 336 | 337 | The type of the extension the namespace refers to, e.g. 338 | Component, Plugin, or Module. 339 | 340 | 341 | 342 | (for plugins) The plugin type i.e. the folder it's installed 343 | into, e.g. System, Content, and so on. 344 | 345 | 346 | 347 | The name of the extension, either as installed (e.g. ARS for 348 | com_ars) or as commonly referred to in the extensions manager (e.g. 349 | ReleaseSystem for com_ars). 350 | 351 | 352 | 353 | Thus, a namespace like Akeeba\Component\ReleaseSystem gives us a 354 | pretty good idea that it's an extension written by a company called 355 | Akeeba, it's a component and it's name is something with Release System in 356 | it. Hm, it must be Akeeba Release System! 357 | 358 | It is a very good idea that parts of your namespace when searched in 359 | the extensions manager end up listing your extension. This will help a 360 | user faced with an exception error page to figure out which extension the 361 | exception comes from, even though they have no idea about PHP or what an 362 | exception is. 363 | 364 | If you get Class Not Found while developing 365 | extensions 366 | 367 | Joomla automatically creates a map of installed extensions, their 368 | location and their namespace prefixes as noted in their XML manifests. It 369 | uses this information to register a PSR-4 autoloader which handles loading 370 | the various classes based on their name, without having to manually 371 | include their files yourself. 372 | 373 | The information is cached in the file 374 | administrator/cache/autoload_psr4.php which is 375 | automatically generated on every page load if it's missing. It is also 376 | forcibly regenerated when you install, update, remove, publish, or 377 | unpublish an extension from your site. 378 | 379 | It is possible that while developing your site you will end up with 380 | that file becoming out of sync with the XML manifests on your filesystem — 381 | for example, if you changed the namespace of an extension you are 382 | developing or if you moved files around. If that happens to you, simply 383 | delete the administrator/cache/autoload_psr4.php file 384 | and reload the frontend home page of your site. The file will be 385 | regenerated. 386 | 387 | If something is missing from that file or if you keep getting 388 | problems despite that file appearing to be correct, ask yourself these 389 | questions: 390 | 391 | 392 | 393 | Am I using the correct class name? Writing this book I've typed 394 | Acme\Component\Examlpe instead of 395 | Acme\Component\Example more times than I care 396 | to admit. Always start with the assumption that you typed the class 397 | name wrong. 398 | 399 | 400 | 401 | Are my folders and files the correct letter case? Attention 402 | macOS and Windows users! While on macOS and Windows the folders 403 | FooBar, FOOBAR and 404 | foobar will all work this is not true on Linux! 405 | Also remember that if you commit a folder / file in the wrong case on 406 | Git you can't just rename it and commit it; it will not work when 407 | checking out the file. Instead rename the folder / file to its correct 408 | case with a -bak suffix, commit, remove the 409 | suffix, commit again. 410 | 411 | 412 | 413 | Is the extension installed? You'd be surprised at how wrapped up 414 | you can get writing the code of the extension without remembering to 415 | actually install it on your development site. I do that every second 416 | plugin I write. At least I know that I'm both the detective and the 417 | killer in this code murder mystery, having gone through it so 418 | often. 419 | 420 | 421 | 422 | Is the extension published? When you install a plugin it is 423 | disabled by default. Disabled extensions don't get autoloaded. 424 | 425 | 426 | 427 | Am I using OPcache? If you're using OPcache —or any other PHP 428 | cache— your server might “remember” the older version of the 429 | autoload_psr4.php file. If unsure, restart the 430 | web server and the PHP-FPM service. 431 | 432 | 433 | 434 | Have I cleared Joomla's cache? If you toggled the publish status 435 | of an extension in the database Joomla might not be aware that you did 436 | so (especially salient for plugins and modules). Clear Joomla's cache, 437 | administrator and site. 438 | 439 | 440 | 441 | Am I using another cache, CDN or reverse proxy between my 442 | browser and the server? Don't do that during development! 443 | 444 | 445 | 446 | Does the XML manifest exist in the location Joomla expects it 447 | and up-to-date? Components' XML manifests must 448 | exist in the component's backend root (e.g. 449 | administrator/components/com_example/example.xml). 450 | Plugins and modules expect the XML manifest in their respective 451 | folder. Make sure the manifest file you have there actually has the 452 | <namespace> tag, the namespace is spelled correctly 453 | and it has a path attribute which is also 454 | spelled correctly, both itself and the folder name which is your PSR-4 455 | root (usually set to "src"). 456 | 457 | 458 | 459 | Is it possible that my namespace violates the two rules 460 | described above, especially the one about it not being a subset of 461 | another extension's namespace? If your namespace is a subset of 462 | another extension (e.g. my namespace is 463 | Acme\Component\Example\Foo and there's another 464 | extension with the namespace 465 | Acme\Component\Example) the PSR-4 autoloader 466 | will end up looking into the wrong folder for 467 | your files. 468 | 469 | 470 |
471 | 472 |
473 | Dependency Injection Container / Service Locator 474 | 475 | Joomla had historically been quite a mess, architecturally speaking. 476 | Its saving grace was that it was a far smaller mess than WordPress and 477 | much more approachable to non-expert coders than Drupal. This let it carve 478 | a niche for itself: people who wanted a very powerful site without having 479 | to first acquire a PhD in Computer Science and/or have a team of dozens of 480 | developers under them. In short, Joomla's bad-but-not-too-bad architecture 481 | let it be used by small web design firms, freelance site integrators and 482 | small but serious software development firms. 483 | 484 | That said, Joomla 1.x to 3.x inclusive had a God Object 486 | called the Joomla Factory (JFactory or 487 | \Joomla\CMS\Factory) with a very opinionated approach on 488 | instantiating all sorts of globally used services, from the application 489 | itself, to the database, to the user objects, to the mailer object. 490 | 491 | While this is a better approach to using global variables (like 492 | WordPress' infamous $wpdb for accessing the database), this 493 | architecture caused a lot of pain when you wanted to write Unit Tests for 494 | your code. Your code gets user instances? You need to create a mock for 495 | the entire Factory object returning mock user objects. Your code uses the 496 | database? You need to create a mock database object and inject it to an 497 | uninitialised Factory instance using static class variables. Your code 498 | sends email? Not only you need a mock mailer object, you need to mock the 499 | Factory too. Want to write tests which mock different things in different 500 | tests? You can either forget about running your tests as a suite OR you 501 | need to create an extremely over-reaching and hard to configure mock 502 | Factory. Your tests must run in a different order? Good luck figuring out 503 | the bugs in your Factory mock object and why running tests in one order 504 | works but fails when run in a different order, or on their lonesome. Been 505 | there, done that, still paying for therapy… 506 | 507 | In Joomla 4 we no longer have a God Object. Well, to be fair, the 508 | Factory is still there but it is no longer a God Object; it is an 509 | interface to a Dependency 511 | Injection Container (DIC for short, pronounced 512 | like Dee Eye See, not the nickname for a Richard, thank you very much). 513 | So, Factory is still a God Object but with lesser powers. A minor deity 514 | object, perhaps? In any case, the Container is initialised before Factory 515 | is used and it can also be replaced. Therefore you only need to get a copy 516 | of the DIC and replace one or more of its services with a mock object when 517 | writing Unit Tests. Much easier, much more robust, no more therapy 518 | necessary after writing Unit Tests. 519 | 520 | The Container is now the preferred way to get access to several 521 | services previously available only through the Factory (they are still 522 | available through the Factory in Joomla 4 but will very likely disappear 523 | in Joomla 5). Let's see a few practical examples: 524 | 525 | use \Joomla\CMS\Factory; 526 | 527 | // Instead of Factory::getDbo(); 528 | $db = Factory::getContainer()->get('DatabaseDriver'); 529 | 530 | // Instead of Factory::getLanguage(); WARNING! STILL DOES NOT WORK EXACTLY AS INTENDED! 531 | $language = Factory::getContainer()->get(LanguageFactoryInterface::class)->createLanguage( 532 | Factory::getApplication()->get('language'), 533 | Factory::getApplication()->get('debug_lang'), 534 | ); 535 | 536 | // Instead of Factory::getUser($id) 537 | $user = Factory::getContainer()->get(UserFactoryInterface::class)->loadUserById($id); 538 | 539 | // Instead of Factory::getUser() with no arguments; note that this does NOT go through the DIC! 540 | $currentUser = Factory::getApplication()->getIdentity(); 541 | 542 | That said, Joomla's DIC is not a real DIC; it is in fact a Service 544 | Locator. That is to say, you don't ask the DIC to construct an 545 | object and expect it to inject the appropriate dependencies based on the 546 | class type hints of the constructor's arguments. In theory it can (kind 547 | of), but in practice this is NOT how the Joomla core API classes are 548 | written. If you came here expecting a DIC like what you find in Laravel, 549 | sorry, I have to disappoint you. 550 | 551 | Now, you are thinking, does this not make the DIC kinda useless? No, 552 | not really. You see, being a Service Locator you get a 553 | copy of it when your extension is initialised. In 554 | fact, each native Joomla 4 extension needs to have a Service Provider 555 | which takes the DIC copy as input and registers services to it. At the 556 | very least you will be registering your extension service which is used by 557 | Joomla to instantiate your extension's object and run its code. You can 558 | also register any number of services you might need, even custom ones only 559 | to be used by your extension. 560 | 561 | At some point in the future Joomla will MAYBE remove the Factory, if 562 | not altogether then at least insofar it can only return the main 563 | application's DIC. In such a future Joomla will VERY PROBABLY make it much 564 | easier for an extension's internal classes to have access to its own DIC / 565 | Service Locator instead of only ever making it available to the Extension 566 | class. In this potential future Joomla extensions will be self-contained 567 | and perfectly testable. Even better, they can be sure that whatever 568 | happens in an extension stays in the extension, without leaking to the 569 | global application scope (and poison other extensions). 570 |
571 | 572 |
573 | Web Asset Management 574 | 575 | A large part of our work as Joomla extension developers is to load 576 | static assets, CSS and JavaScript files, in the user-facing HTML output of 577 | our extensions. 578 | 579 | In older Joomla versions we did that through the HTML document and 580 | using HTMLHelper static methods to load dependencies. For example: 581 | 582 | $doc = \Joomla\CMS\Factory::getApplication()->getDocument(); 583 | Joomla\CMS\HTML\HTMLHelper::_('bootstrap.tooltip', '.hasTooltip'); 584 | Joomla\CMS\HTML\HTMLHelper::_('script', 'com_example/something.js', [ 585 | 'version' => 'auto', 586 | 'relative' => true, 587 | 'detectDebug' => false, 588 | 'framework' => false, 589 | 'pathOnly' => false, 590 | 'detectBrowser' => false, 591 | ], [ 592 | 'defer' => true, 593 | 'async' => false, 594 | ]); 595 | 596 | This has a few shortcomings, as we have all discovered to our 597 | despair. 598 | 599 | First of all, we need to remember to load all dependencies in the 600 | correct order before our own CSS or JavaScript file. In the above example, 601 | the something.js file depends on Bootstrap's Tooltip helper. If we forget 602 | the first call to HTMLHelper our JavaScript file will be broken. 603 | 604 | However, our extension is not the only thing running on the page, 605 | right? Now, see the second parameter in that first HTMLHelper call? It 606 | tells Joomla's Bootstrap HTML helper to initialise the Tooltip helper so 607 | that anything with the class hasTooltip will have a Bootstrap tooltip. 608 | Since this is a component we are confident that this will always be the 609 | case. Oh, really? If a plugin ran before us and it also loaded its own 610 | JavaScript which also depends on Bootstrap's tooltip BUT had no second 611 | argument (or a different second argument) do you care to guess what our 612 | code above will do? If you guessed “sod all” you'd be right and a Joomla 613 | extensions development veteran! So, yup, a third party extension having a 614 | JavaScript file with the same dependency as ours running before us breaks 615 | our perfectly working JavaScript. This could even happen within the same 616 | extension if the aforementioned code appeared in a layout and your page 617 | just happens to load two layout which both call 618 | Joomla\CMS\HTML\HTMLHelper::_('bootstrap.tooltip') with a 619 | different second parameter. Great! 620 | 621 | Beyond that, what happens if our something.js gains another 622 | dependency and we are loading this file in six different places… but 623 | missed updating one of them? Why, yes, that sixth page will be broken! 624 | Even worse, we might only update our code with the additional dependency 625 | in one place (let's say a layout), another four places not updated work 626 | because they are loading that changed layout and the sixth and final place 627 | does not work because it was neither updated nor trying to load something 628 | else which loads the dependency for us. 629 | 630 | Let's put it this way. If you do manual dependency management you 631 | will be in a world of pain, sooner rather than later. 632 | 633 | Joomla 4 addresses this problem by introducing the Web Asset Manager 634 | (WAM). The WAM is responsible for loading our CSS and JavaScript files 635 | and their dependencies. It can figure out simple 636 | dependency chains even across multiple extensions and make sure that 637 | things are loaded in an order that makes sense and will do what we wanted 638 | it to do. 639 | 640 | For that to work we need two things: 641 | 642 | 643 | 644 | Using Joomla's media directory the way it was intended ever 645 | since its introduction in Joomla 1.5.0, back in 2007. 646 | 647 | 648 | 649 | A joomla.assets.json file which describes 650 | our static assets and their dependencies. 651 | 652 | 653 | 654 | On the first point please let me remind you how the media folder 655 | works. If you have any static assets which must be web accessible they 656 | MUST be placed in a subdirectory of the 657 | media folder named after your extension (as Joomla 658 | names it internally). Don't put them in your extension's directory, don't 659 | put them in cache or tmp (they 660 | are NOT web accessible, they CAN be moved around even outside the web root 661 | AND their contents can and will be removed anytime). 662 | 663 | You have a component named com_foobar? Put your static 664 | assets in media/com_foobar. You have a module named 665 | mod_example? Put your static assets in 666 | media/mod_example. You have a plugin named 667 | example in the folder system? Put your 668 | static assets in media/plg_system_example. You have a 669 | template named beauty? Put your static assets in 670 | media/tpl_beauty. Its subdirectories are 671 | css for CSS files and js for 672 | JavaScript files. It's simple, it's efficient, it's how Joomla is meant to 673 | work. 674 | 675 | The second point, the joomla.assets.json file, 676 | tells Joomla where to find what, what depends on what else and how it all 677 | fits together. This file is placed in the extension's media 678 | subdirectory. 679 | 680 | For example, a component com_example could have a 681 | media/com_example/joomla.asset.json file which looks 682 | like this: 683 | 684 | { 685 | "$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json", 686 | "name": "com_example", 687 | "version": "1.0.0", 688 | "description": "This file contains details of the assets used by the Example component by Acme, Inc.", 689 | "license": "GPL-2.0-or-later", 690 | "assets": [ 691 | { 692 | "name": "com_example.backend", 693 | "description": "Backend styling.", 694 | "type": "style", 695 | "uri": "com_example/backend.min.css", 696 | "dependencies": [ 697 | "com_example.typography" 698 | ] 699 | }, 700 | { 701 | "name": "com_example.typography", 702 | "description": "Fancy typography.", 703 | "type": "style", 704 | "uri": "com_example/typography.min.css", 705 | "dependencies": [ 706 | "fontawesome" 707 | ] 708 | }, 709 | { 710 | "name": "com_example.backend.items", 711 | "description": "JavaScript for the backend Items page.", 712 | "type": "script", 713 | "uri": "com_example/backend_items.js", 714 | "attributes" : { 715 | "defer": true 716 | }, 717 | "dependencies": [ 718 | "core" 719 | ] 720 | }, 721 | { 722 | "name": "com_example.backend.items", 723 | "type": "preset", 724 | "dependencies": [ 725 | "com_example.backend#style", 726 | "com_example.backend.items#script" 727 | ] 728 | } 729 | ] 730 | } 731 | 732 | We declare various named assets. The 733 | com_example.backend style asset loads the 734 | backend.min.css file. However, that file depends on 735 | the com_example.typography asset which loads the 736 | typography.min.css file. In its turn, this asset 737 | depends on the core fontawesome asset which loads the 738 | FontAwesome icon font in any way Joomla figures out is appropriate. 739 | 740 | When we tell Joomla to load the com_example.backend 741 | style asset it will first load the CSS files for FontAwesome (if our 742 | backend template has not already loaded it), then our 743 | typography.min.css file and finally our 744 | backend.min.css file. This all happens automatically. 745 | All we have to do in our extension's template layout code is 746 | 747 | $this->document->getWebAssetManager()->useStyle('com_example.backend'); 748 | 749 | If at a later point we decide that the backend style needs to 750 | depends on yet another CSS asset we will add it to its dependencies array 751 | in the joomla.asset.json file and we are 752 | done. We do not have to touch our view templates. We do not 753 | have to think about anything else. Joomla will figure it out. No more hard 754 | to track down bugs! 755 | 756 | You may have noticed that we also declared a script asset called 757 | com_example.backend.items which loads the file 758 | backend_items.js deferred. Deferred means that we 759 | tell the browser to load it after it has finished initialising the DOM. 760 | This means that we do not need to add any special code to execute 761 | something after the DOM is initialised which saves us a lot of frustration 762 | and bugs. We use the script resource like this: 763 | 764 | $this->document->getWebAssetManager()->useScript('com_example.backend.items'); 765 | 766 | We have told Joomla that our script only depends on 767 | core, i.e. the Joomla core JavaScript. This is not mandatory, 768 | but something you will see plenty of times because you'll be using 769 | Joomla.getOptions in your JavaScript code to retrieve 770 | settings passed from the backend to 771 | the frontend. This is the recommended method instead of setting 772 | arbitrary JavaScript variables in inline JavaScript code. In fact, using 773 | inline JavaScript code is discouraged (but not forbidden) in Joomla 4 and 774 | later. 775 | 776 | If at a later point we modify our JavaScript to also depend on 777 | Bootstrap's Modal dialog helper we will just update its 778 | dependencies: 779 | 780 | { 781 | "name": "com_example.backend.items", 782 | "description": "JavaScript for the backend Items page.", 783 | "type": "script", 784 | "uri": "backend_items.js", 785 | "attributes" : { 786 | "defer": true 787 | }, 788 | "dependencies": [ 789 | "core", 790 | "bootstrap.modal" 791 | ] 792 | } 793 | 794 | That's it! No more hunting down usages of this JavaScript file and 795 | updating our view template code. 796 | 797 | You can of course tell Joomla to load both CSS and JavaScript 798 | assets. The simplest way is being descriptive in our view template: 799 | 800 | $this->document->getWebAssetManager() 801 | ->useStyle('com_example.backend') 802 | ->useScript('com_example.backend.items'); 803 | 804 | (note that useStyle and useScript return the WAM object which means 805 | they can be chain-called) 806 | 807 | However, this runs the same risk as loading assets the old-fashioned 808 | way. What happens if we decide that the Items page needs some extra CSS 809 | which does not apply to the rest of our component's backend? We'd have to 810 | edit the template layout file. Enter bugs. 811 | 812 | Instead of being descriptive we can be 813 | prescriptive using another WAM feature called 814 | presets. A preset consists entirely of 815 | dependencies. We declared it in our JSON file like this: 816 | 817 | { 818 | "name": "com_example.backend.items", 819 | "type": "preset", 820 | "dependencies": [ 821 | "com_example.backend#style", 822 | "com_example.backend.items#script" 823 | ] 824 | } 825 | 826 | 827 | and we can load it in our view template very easily like 828 | this: 829 | 830 | $this->document->getWebAssetManager()->usePreset('com_example.backend.items'); 831 | 832 | Note that the preset asset's key is the same as our script asset's 833 | key. Script, style and preset assets are separate collections which means 834 | we can reuse the same key across them. Joomla will 835 | not be confused. We tell it which collection to look into by using a 836 | different WAM method: useScript, useStyle or 837 | usePreset. 838 | 839 | Now let's see why presets are the bee's knees. Let's say we decided 840 | that Items also needs some special styling in a separate CSS file called 841 | items.min.css. We will just add this asset to our 842 | JSON file and update the preset: 843 | 844 | { 845 | "name": "com_example.backend.items", 846 | "description": "Backend styling just for the Items page.", 847 | "type": "style", 848 | "uri": "items.min.css", 849 | "dependencies": [ 850 | "com_example.backend" 851 | ] 852 | }, 853 | { 854 | "name": "com_example.backend.items", 855 | "type": "preset", 856 | "dependencies": [ 857 | "com_example.backend#style", 858 | "com_example.backend.items#style", 859 | "com_example.backend.items#script" 860 | ] 861 | } 862 | 863 | 864 | (You may notice that our com_example.backend.items 865 | asset depends on com_example.backend. I didn't have to do 866 | that, but I like to be explicit about dependencies to avoid any stupid 867 | bugs if I remove any intermediate dependencies in a dependency 868 | chain.) 869 | 870 | We do NOT have to touch our view template file. Since we are telling 871 | it to load a preset, changing the preset is enough for Joomla to figure 872 | out what it needs to do. 873 | 874 | Using the Web Asset Manager correctly can be a massive asset (no pun 875 | intended!) in your extensions' public frontend. Your view templates can 876 | load your prescriptive presets. If you decide you want to change something 877 | you can change the preset. Your clients who have created template 878 | overrides will NOT need to update their overrides. This means far fewer 879 | “bug” reports and more time for you to work on your code. 880 | 881 | The Web Asset Manager has changed the way I write extensions and has 882 | solved a lot of my headaches. You can use the WAM on any component running 883 | on Joomla 4, regardless of whether you are using the “old” (Joomla 3) MVC 884 | or the “new” (Joomla 4) MVC. In fact, since it is a part of the Joomla 885 | document object, you can use it in modules, even plugins — however, if you 886 | are using it in a plugin you MUST tell the WAM to load your JSON file 887 | since Joomla will not do that by default for plugins. 888 | 889 | Finally, the WAM is a much less error-prone method to injecting 890 | static assets to Joomla. All Joomla document classes have a WAM, even when 891 | they are not HTML; it just follows that if it's a non-HTML document adding 892 | an asset through WAM does nothing. Compare that with what happens if you 893 | try to use the HTMLHelper or the addScript / addStyle document methods 894 | when your document is not HTML. Yup, these old ways of adding static 895 | assets cause Joomla to error out. Again, WAM is safe, the methods of 896 | yesteryear are not. One more reason to migrate your extensions to WAM 897 | today. 898 | 899 | Caveat: modules don't auto-load the 900 | joomla.asset.json file 901 | 902 | Modules do not auto-load the joomla.asset.json 903 | file. You will need to load it yourself with: 904 | 905 | $wa = \Joomla\CMS\Factory::getApplication() 906 | ->getDocument() 907 | ->getWebAssetManager(); 908 | $wa 909 | ->getRegistry() 910 | ->addRegistryFile(JPATH_ROOT . '/media/mod_mymodule/joomla.asset.json'); 911 | 912 | Alternatively, you can register and load each separate dependency in 913 | your view template file, like Joomla's core modules do, even though that's 914 | NOT a recommended or sustainable practice: 915 | 916 | $wa = \Joomla\CMS\Factory::getApplication() 917 | ->getDocument() 918 | ->getWebAssetManager(); 919 | $wa 920 | ->registerAndUseScript( 921 | 'mod_mymodule.something', 922 | 'mod_mymodule/something.min.js', 923 | [], 924 | ['defer' => true], 925 | ['core'] 926 | ); 927 | 928 | Caveat: templates have a weird location for the 929 | joomla.asset.json file 930 | 931 | In Joomla 3 and 4.0 you are supposed to put the template's static 932 | files inside your template's subdirectory: 933 | templates/TEMPLATE_NAME 934 | for front-end templates, or 935 | administrator/templates/TEMPLATE_NAME 936 | for back-end templates, where TEMPLATE_NAME is 937 | the name of your template without the tpl_ prefix. 938 | 939 | In Joomla 4.1 and later versions you are supposed to put the 940 | template's static files inside a media subdirectory: 941 | media/templates/site/TEMPLATE_NAME 942 | for front-end templates, or 943 | media/templates/administrator/TEMPLATE_NAME 944 | for back-end templates, where TEMPLATE_NAME is 945 | the name of your template without the tpl_ prefix. As of 946 | Joomla 6 this will be the only supported method. It is definitely the only 947 | supported method since Joomla 4.1 for templates which have support for 948 | child templates. 949 | 950 | In both cases you have to put your 951 | joomla.asset.json file inside your template's subdirectory: 952 | templates/TEMPLATE_NAME 953 | for front-end templates, or 954 | administrator/templates/TEMPLATE_NAME 955 | for back-end templates, where TEMPLATE_NAME is 956 | the name of your template without the tpl_ prefix. This may 957 | look a bit weird, but it's there for legacy reasons. Templates with the 958 | old-style static resources wouldn't work otherwise. 959 |
960 |
961 | -------------------------------------------------------------------------------- /sections/fdl.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | GNU Free Documentation License 14 | 15 | Version 1.3, 3 November 2008 16 | 17 | Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, 19 | Inc. 20 | 21 | Everyone is permitted to copy and distribute verbatim copies of 22 | this license document, but changing it is not allowed. 23 | 24 | 0. PREAMBLE 25 | 26 | The purpose of this License is to make a manual, textbook, or 27 | other functional and useful document “free” in the sense of freedom: to 28 | assure everyone the effective freedom to copy and redistribute it, with or 29 | without modifying it, either commercially or noncommercially. Secondarily, 30 | this License preserves for the author and publisher a way to get credit 31 | for their work, while not being considered responsible for modifications 32 | made by others. 33 | 34 | This License is a kind of “copyleft”, which means that derivative 35 | works of the document must themselves be free in the same sense. It 36 | complements the GNU General Public License, which is a copyleft license 37 | designed for free software. 38 | 39 | We have designed this License in order to use it for manuals for 40 | free software, because free software needs free documentation: a free 41 | program should come with manuals providing the same freedoms that the 42 | software does. But this License is not limited to software manuals; it can 43 | be used for any textual work, regardless of subject matter or whether it 44 | is published as a printed book. We recommend this License principally for 45 | works whose purpose is instruction or reference. 46 | 47 | 1. APPLICABILITY AND 48 | DEFINITIONS 49 | 50 | This License applies to any manual or other work, in any medium, 51 | that contains a notice placed by the copyright holder saying it can be 52 | distributed under the terms of this License. Such a notice grants a 53 | world-wide, royalty-free license, unlimited in duration, to use that work 54 | under the conditions stated herein. The “Document”, below, refers to any 55 | such manual or work. Any member of the public is a licensee, and is 56 | addressed as “you”. You accept the license if you copy, modify or 57 | distribute the work in a way requiring permission under copyright 58 | law. 59 | 60 | A “Modified Version” of the Document means any work containing 61 | the Document or a portion of it, either copied verbatim, or with 62 | modifications and/or translated into another language. 63 | 64 | A “Secondary Section” is a named appendix or a front-matter 65 | section of the Document that deals exclusively with the relationship of 66 | the publishers or authors of the Document to the Document's overall 67 | subject (or to related matters) and contains nothing that could fall 68 | directly within that overall subject. (Thus, if the Document is in part a 69 | textbook of mathematics, a Secondary Section may not explain any 70 | mathematics.) The relationship could be a matter of historical connection 71 | with the subject or with related matters, or of legal, commercial, 72 | philosophical, ethical or political position regarding them. 73 | 74 | The “Invariant Sections” are certain Secondary Sections whose 75 | titles are designated, as being those of Invariant Sections, in the notice 76 | that says that the Document is released under this License. If a section 77 | does not fit the above definition of Secondary then it is not allowed to 78 | be designated as Invariant. The Document may contain zero Invariant 79 | Sections. If the Document does not identify any Invariant Sections then 80 | there are none. 81 | 82 | The “Cover Texts” are certain short passages of text that are 83 | listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says 84 | that the Document is released under this License. A Front-Cover Text may 85 | be at most 5 words, and a Back-Cover Text may be at most 25 86 | words. 87 | 88 | A “Transparent” copy of the Document means a machine-readable 89 | copy, represented in a format whose specification is available to the 90 | general public, that is suitable for revising the document 91 | straightforwardly with generic text editors or (for images composed of 92 | pixels) generic paint programs or (for drawings) some widely available 93 | drawing editor, and that is suitable for input to text formatters or for 94 | automatic translation to a variety of formats suitable for input to text 95 | formatters. A copy made in an otherwise Transparent file format whose 96 | markup, or absence of markup, has been arranged to thwart or discourage 97 | subsequent modification by readers is not Transparent. An image format is 98 | not Transparent if used for any substantial amount of text. A copy that is 99 | not “Transparent” is called “Opaque”. 100 | 101 | Examples of suitable formats for Transparent copies include plain 102 | ASCII without markup, Texinfo input format, LaTeX input format, SGML or 103 | XML using a publicly available DTD, and standard-conforming simple HTML, 104 | PostScript or PDF designed for human modification. Examples of transparent 105 | image formats include PNG, XCF and JPG. Opaque formats include proprietary 106 | formats that can be read and edited only by proprietary word processors, 107 | SGML or XML for which the DTD and/or processing tools are not generally 108 | available, and the machine-generated HTML, PostScript or PDF produced by 109 | some word processors for output purposes only. 110 | 111 | The “Title Page” means, for a printed book, the title page 112 | itself, plus such following pages as are needed to hold, legibly, the 113 | material this License requires to appear in the title page. For works in 114 | formats which do not have any title page as such, “Title Page” means the 115 | text near the most prominent appearance of the work's title, preceding the 116 | beginning of the body of the text. 117 | 118 | The “publisher” means any person or entity that distributes 119 | copies of the Document to the public. 120 | 121 | A section “Entitled XYZ” means a named subunit of the Document 122 | whose title either is precisely XYZ or contains XYZ in parentheses 123 | following text that translates XYZ in another language. (Here XYZ stands 124 | for a specific section name mentioned below, such as “Acknowledgements”, 125 | “Dedications”, “Endorsements”, or “History”.) To “Preserve the Title” of 126 | such a section when you modify the Document means that it remains a 127 | section “Entitled XYZ” according to this definition. 128 | 129 | The Document may include Warranty Disclaimers next to the notice 130 | which states that this License applies to the Document. These Warranty 131 | Disclaimers are considered to be included by reference in this License, 132 | but only as regards disclaiming warranties: any other implication that 133 | these Warranty Disclaimers may have is void and has no effect on the 134 | meaning of this License. 135 | 136 | 2. VERBATIM 137 | COPYING 138 | 139 | You may copy and distribute the Document in any medium, either 140 | commercially or noncommercially, provided that this License, the copyright 141 | notices, and the license notice saying this License applies to the 142 | Document are reproduced in all copies, and that you add no other 143 | conditions whatsoever to those of this License. You may not use technical 144 | measures to obstruct or control the reading or further copying of the 145 | copies you make or distribute. However, you may accept compensation in 146 | exchange for copies. If you distribute a large enough number of copies you 147 | must also follow the conditions in section 3. 148 | 149 | You may also lend copies, under the same conditions stated above, 150 | and you may publicly display copies. 151 | 152 | 3. COPYING IN 153 | QUANTITY 154 | 155 | If you publish printed copies (or copies in media that commonly 156 | have printed covers) of the Document, numbering more than 100, and the 157 | Document's license notice requires Cover Texts, you must enclose the 158 | copies in covers that carry, clearly and legibly, all these Cover Texts: 159 | Front-Cover Texts on the front cover, and Back-Cover Texts on the back 160 | cover. Both covers must also clearly and legibly identify you as the 161 | publisher of these copies. The front cover must present the full title 162 | with all words of the title equally prominent and visible. You may add 163 | other material on the covers in addition. Copying with changes limited to 164 | the covers, as long as they preserve the title of the Document and satisfy 165 | these conditions, can be treated as verbatim copying in other 166 | respects. 167 | 168 | If the required texts for either cover are too voluminous to fit 169 | legibly, you should put the first ones listed (as many as fit reasonably) 170 | on the actual cover, and continue the rest onto adjacent pages. 171 | 172 | If you publish or distribute Opaque copies of the Document 173 | numbering more than 100, you must either include a machine-readable 174 | Transparent copy along with each Opaque copy, or state in or with each 175 | Opaque copy a computer-network location from which the general 176 | network-using public has access to download using public-standard network 177 | protocols a complete Transparent copy of the Document, free of added 178 | material. If you use the latter option, you must take reasonably prudent 179 | steps, when you begin distribution of Opaque copies in quantity, to ensure 180 | that this Transparent copy will remain thus accessible at the stated 181 | location until at least one year after the last time you distribute an 182 | Opaque copy (directly or through your agents or retailers) of that edition 183 | to the public. 184 | 185 | It is requested, but not required, that you contact the authors 186 | of the Document well before redistributing any large number of copies, to 187 | give them a chance to provide you with an updated version of the 188 | Document. 189 | 190 | 4. 191 | MODIFICATIONS 192 | 193 | You may copy and distribute a Modified Version of the Document 194 | under the conditions of sections 2 and 3 above, provided that you release 195 | the Modified Version under precisely this License, with the Modified 196 | Version filling the role of the Document, thus licensing distribution and 197 | modification of the Modified Version to whoever possesses a copy of it. In 198 | addition, you must do these things in the Modified Version: 199 | 200 | 201 | 202 | Use in the Title Page (and on the covers, if any) a title 203 | distinct from that of the Document, and from those of previous 204 | versions (which should, if there were any, be listed in the History 205 | section of the Document). You may use the same title as a previous 206 | version if the original publisher of that version gives 207 | permission. 208 | 209 | 210 | 211 | List on the Title Page, as authors, one or more persons or 212 | entities responsible for authorship of the modifications in the 213 | Modified Version, together with at least five of the principal authors 214 | of the Document (all of its principal authors, if it has fewer than 215 | five), unless they release you from this requirement. 216 | 217 | 218 | 219 | State on the Title page the name of the publisher of the 220 | Modified Version, as the publisher. 221 | 222 | 223 | 224 | Preserve all the copyright notices of the Document. 225 | 226 | 227 | 228 | Add an appropriate copyright notice for your modifications 229 | adjacent to the other copyright notices. 230 | 231 | 232 | 233 | Include, immediately after the copyright notices, a license 234 | notice giving the public permission to use the Modified Version under 235 | the terms of this License, in the form shown in the Addendum 236 | below. 237 | 238 | 239 | 240 | Preserve in that license notice the full lists of Invariant 241 | Sections and required Cover Texts given in the Document's license 242 | notice. 243 | 244 | 245 | 246 | Include an unaltered copy of this License. 247 | 248 | 249 | 250 | Preserve the section Entitled “History”, Preserve its Title, 251 | and add to it an item stating at least the title, year, new authors, 252 | and publisher of the Modified Version as given on the Title Page. If 253 | there is no section Entitled “History” in the Document, create one 254 | stating the title, year, authors, and publisher of the Document as 255 | given on its Title Page, then add an item describing the Modified 256 | Version as stated in the previous sentence. 257 | 258 | 259 | 260 | Preserve the network location, if any, given in the Document 261 | for public access to a Transparent copy of the Document, and likewise 262 | the network locations given in the Document for previous versions it 263 | was based on. These may be placed in the “History” section. You may 264 | omit a network location for a work that was published at least four 265 | years before the Document itself, or if the original publisher of the 266 | version it refers to gives permission. 267 | 268 | 269 | 270 | For any section Entitled “Acknowledgements” or “Dedications”, 271 | Preserve the Title of the section, and preserve in the section all the 272 | substance and tone of each of the contributor acknowledgements and/or 273 | dedications given therein. 274 | 275 | 276 | 277 | Preserve all the Invariant Sections of the Document, 278 | unaltered in their text and in their titles. Section numbers or the 279 | equivalent are not considered part of the section titles. 280 | 281 | 282 | 283 | Delete any section Entitled “Endorsements”. Such a section 284 | may not be included in the Modified Version. 285 | 286 | 287 | 288 | Do not retitle any existing section to be Entitled 289 | “Endorsements” or to conflict in title with any Invariant 290 | Section. 291 | 292 | 293 | 294 | Preserve any Warranty Disclaimers. 295 | 296 | 297 | 298 | If the Modified Version includes new front-matter sections or 299 | appendices that qualify as Secondary Sections and contain no material 300 | copied from the Document, you may at your option designate some or all of 301 | these sections as invariant. To do this, add their titles to the list of 302 | Invariant Sections in the Modified Version's license notice. These titles 303 | must be distinct from any other section titles. 304 | 305 | You may add a section Entitled “Endorsements”, provided it 306 | contains nothing but endorsements of your Modified Version by various 307 | parties — for example, statements of peer review or that the text has been 308 | approved by an organization as the authoritative definition of a 309 | standard. 310 | 311 | You may add a passage of up to five words as a Front-Cover Text, 312 | and a passage of up to 25 words as a Back-Cover Text, to the end of the 313 | list of Cover Texts in the Modified Version. Only one passage of 314 | Front-Cover Text and one of Back-Cover Text may be added by (or through 315 | arrangements made by) any one entity. If the Document already includes a 316 | cover text for the same cover, previously added by you or by arrangement 317 | made by the same entity you are acting on behalf of, you may not add 318 | another; but you may replace the old one, on explicit permission from the 319 | previous publisher that added the old one. 320 | 321 | The author(s) and publisher(s) of the Document do not by this 322 | License give permission to use their names for publicity for or to assert 323 | or imply endorsement of any Modified Version. 324 | 325 | 5. COMBINING 326 | DOCUMENTS 327 | 328 | You may combine the Document with other documents released under 329 | this License, under the terms defined in section 4 above for modified 330 | versions, provided that you include in the combination all of the 331 | Invariant Sections of all of the original documents, unmodified, and list 332 | them all as Invariant Sections of your combined work in its license 333 | notice, and that you preserve all their Warranty Disclaimers. 334 | 335 | The combined work need only contain one copy of this License, and 336 | multiple identical Invariant Sections may be replaced with a single copy. 337 | If there are multiple Invariant Sections with the same name but different 338 | contents, make the title of each such section unique by adding at the end 339 | of it, in parentheses, the name of the original author or publisher of 340 | that section if known, or else a unique number. Make the same adjustment 341 | to the section titles in the list of Invariant Sections in the license 342 | notice of the combined work. 343 | 344 | In the combination, you must combine any sections Entitled 345 | “History” in the various original documents, forming one section Entitled 346 | “History”; likewise combine any sections Entitled “Acknowledgements”, and 347 | any sections Entitled “Dedications”. You must delete all sections Entitled 348 | “Endorsements”. 349 | 350 | 6. COLLECTIONS OF 351 | DOCUMENTS 352 | 353 | You may make a collection consisting of the Document and other 354 | documents released under this License, and replace the individual copies 355 | of this License in the various documents with a single copy that is 356 | included in the collection, provided that you follow the rules of this 357 | License for verbatim copying of each of the documents in all other 358 | respects. 359 | 360 | You may extract a single document from such a collection, and 361 | distribute it individually under this License, provided you insert a copy 362 | of this License into the extracted document, and follow this License in 363 | all other respects regarding verbatim copying of that document. 364 | 365 | 7. AGGREGATION WITH 366 | INDEPENDENT WORKS 367 | 368 | A compilation of the Document or its derivatives with other 369 | separate and independent documents or works, in or on a volume of a 370 | storage or distribution medium, is called an “aggregate” if the copyright 371 | resulting from the compilation is not used to limit the legal rights of 372 | the compilation's users beyond what the individual works permit. When the 373 | Document is included in an aggregate, this License does not apply to the 374 | other works in the aggregate which are not themselves derivative works of 375 | the Document. 376 | 377 | If the Cover Text requirement of section 3 is applicable to these 378 | copies of the Document, then if the Document is less than one half of the 379 | entire aggregate, the Document's Cover Texts may be placed on covers that 380 | bracket the Document within the aggregate, or the electronic equivalent of 381 | covers if the Document is in electronic form. Otherwise they must appear 382 | on printed covers that bracket the whole aggregate. 383 | 384 | 8. TRANSLATION 385 | 386 | Translation is considered a kind of modification, so you may 387 | distribute translations of the Document under the terms of section 4. 388 | Replacing Invariant Sections with translations requires special permission 389 | from their copyright holders, but you may include translations of some or 390 | all Invariant Sections in addition to the original versions of these 391 | Invariant Sections. You may include a translation of this License, and all 392 | the license notices in the Document, and any Warranty Disclaimers, 393 | provided that you also include the original English version of this 394 | License and the original versions of those notices and disclaimers. In 395 | case of a disagreement between the translation and the original version of 396 | this License or a notice or disclaimer, the original version will 397 | prevail. 398 | 399 | If a section in the Document is Entitled “Acknowledgements”, 400 | “Dedications”, or “History”, the requirement (section 4) to Preserve its 401 | Title (section 1) will typically require changing the actual 402 | title. 403 | 404 | 9. TERMINATION 405 | 406 | You may not copy, modify, sublicense, or distribute the Document 407 | except as expressly provided under this License. Any attempt otherwise to 408 | copy, modify, sublicense, or distribute it is void, and will automatically 409 | terminate your rights under this License. 410 | 411 | However, if you cease all violation of this License, then your 412 | license from a particular copyright holder is reinstated (a) 413 | provisionally, unless and until the copyright holder explicitly and 414 | finally terminates your license, and (b) permanently, if the copyright 415 | holder fails to notify you of the violation by some reasonable means prior 416 | to 60 days after the cessation. 417 | 418 | Moreover, your license from a particular copyright holder is 419 | reinstated permanently if the copyright holder notifies you of the 420 | violation by some reasonable means, this is the first time you have 421 | received notice of violation of this License (for any work) from that 422 | copyright holder, and you cure the violation prior to 30 days after your 423 | receipt of the notice. 424 | 425 | Termination of your rights under this section does not terminate 426 | the licenses of parties who have received copies or rights from you under 427 | this License. If your rights have been terminated and not permanently 428 | reinstated, receipt of a copy of some or all of the same material does not 429 | give you any rights to use it. 430 | 431 | 10. FUTURE REVISIONS OF 432 | THIS LICENSE 433 | 434 | The Free Software Foundation may publish new, revised versions of 435 | the GNU Free Documentation License from time to time. Such new versions 436 | will be similar in spirit to the present version, but may differ in detail 437 | to address new problems or concerns. See https://www.gnu.org/licenses/. 439 | 440 | Each version of the License is given a distinguishing version 441 | number. If the Document specifies that a particular numbered version of 442 | this License “or any later version” applies to it, you have the option of 443 | following the terms and conditions either of that specified version or of 444 | any later version that has been published (not as a draft) by the Free 445 | Software Foundation. If the Document does not specify a version number of 446 | this License, you may choose any version ever published (not as a draft) 447 | by the Free Software Foundation. If the Document specifies that a proxy 448 | can decide which future versions of this License can be used, that proxy's 449 | public statement of acceptance of a version permanently authorizes you to 450 | choose that version for the Document. 451 | 452 | 11. 453 | RELICENSING 454 | 455 | “Massive Multiauthor Collaboration Site” (or “MMC Site”) means 456 | any World Wide Web server that publishes copyrightable works and also 457 | provides prominent facilities for anybody to edit those works. A public 458 | wiki that anybody can edit is an example of such a server. A “Massive 459 | Multiauthor Collaboration” (or “MMC”) contained in the site means any set 460 | of copyrightable works thus published on the MMC site. 461 | 462 | “CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 463 | license published by Creative Commons Corporation, a not-for-profit 464 | corporation with a principal place of business in San Francisco, 465 | California, as well as future copyleft versions of that license published 466 | by that same organization. 467 | 468 | “Incorporate” means to publish or republish a Document, in whole 469 | or in part, as part of another Document. 470 | 471 | An MMC is “eligible for relicensing” if it is licensed under this 472 | License, and if all works that were first published under this License 473 | somewhere other than this MMC, and subsequently incorporated in whole or 474 | in part into the MMC, (1) had no cover texts or invariant sections, and 475 | (2) were thus incorporated prior to November 1, 2008. 476 | 477 | The operator of an MMC Site may republish an MMC contained in the 478 | site under CC-BY-SA on the same site at any time before August 1, 2009, 479 | provided the MMC is eligible for relicensing. 480 | 481 | ADDENDUM: How to use this 482 | License for your documents 483 | 484 | To use this License in a document you have written, include a 485 | copy of the License in the document and put the following copyright and 486 | license notices just after the title page: 487 | 488 | Copyright © YEAR YOUR NAME 489 | 490 | Permission is granted to copy, distribute and/or modify this document under the 491 | terms of the GNU Free Documentation License, Version 1.3 or any later version 492 | published by the Free Software Foundation; with no Invariant Sections, no 493 | Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in 494 | the section entitled “GNU Free Documentation License”. 495 | 496 | If you have Invariant Sections, Front-Cover Texts and Back-Cover 497 | Texts, replace the “with… Texts.” line with this: 498 | 499 | with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts 500 | being LIST, and with the Back-Cover Texts being LIST. 501 | 502 | If you have Invariant Sections without Cover Texts, or some other 503 | combination of the three, merge those two alternatives to suit the 504 | situation. 505 | 506 | If your document contains nontrivial examples of program code, we 507 | recommend releasing these examples in parallel under your choice of free 508 | software license, such as the GNU General Public License, to permit their 509 | use in free software. 510 | 511 | -------------------------------------------------------------------------------- /sections/gpl.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | GNU General Public License 14 | 15 | Preamble 16 | 17 | The licenses for most software are designed to take away your 18 | freedom to share and change it. By contrast, the GNU General Public 19 | License is intended to guarantee your freedom to share and change free 20 | software - to make sure the software is free for all its users. This 21 | General Public License applies to most of the Free Software Foundation's 22 | software and to any other program whose authors commit to using it. (Some 23 | other Free Software Foundation software is covered by the GNU Library 24 | General Public License instead.) You can apply it to your programs, 25 | too. 26 | 27 | When we speak of free software, we are referring to freedom, not 28 | price. Our General Public Licenses are designed to make sure that you have 29 | the freedom to distribute copies of free software (and charge for this 30 | service if you wish), that you receive source code or can get it if you 31 | want it, that you can change the software or use pieces of it in new free 32 | programs; and that you know you can do these things. 33 | 34 | To protect your rights, we need to make restrictions that forbid 35 | anyone to deny you these rights or to ask you to surrender the rights. 36 | These restrictions translate to certain responsibilities for you if you 37 | distribute copies of the software, or if you modify it. 38 | 39 | For example, if you distribute copies of such a program, whether 40 | gratis or for a fee, you must give the recipients all the rights that you 41 | have. You must make sure that they, too, receive or can get the source 42 | code. And you must show them these terms so they know their rights. 43 | 44 | We protect your rights with two steps: 45 | 46 | 47 | 48 | copyright the software, and 49 | 50 | 51 | 52 | offer you this license which gives you legal permission to copy, 53 | distribute and/or modify the software. 54 | 55 | 56 | 57 | Also, for each author's protection and ours, we want to make certain 58 | that everyone understands that there is no warranty for this free 59 | software. If the software is modified by someone else and passed on, we 60 | want its recipients to know that what they have is not the original, so 61 | that any problems introduced by others will not reflect on the original 62 | authors' reputations. 63 | 64 | Finally, any free program is threatened constantly by software 65 | patents. We wish to avoid the danger that redistributors of a free program 66 | will individually obtain patent licenses, in effect making the program 67 | proprietary. To prevent this, we have made it clear that any patent must 68 | be licensed for everyone's free use or not licensed at all. 69 | 70 | The precise terms and conditions for copying, distribution and 71 | modification follow. 72 | 73 | TERMS AND CONDITIONS FOR COPYING, 74 | DISTRIBUTION AND MODIFICATION 75 | 76 | Section 0 77 | 78 | This License applies to any program or other work which contains a 79 | notice placed by the copyright holder saying it may be distributed under 80 | the terms of this General Public License. The Program, 81 | below, refers to any such program or work, and a work based on the 82 | Program means either the Program or any derivative work under 83 | copyright law: that is to say, a work containing the Program or a portion 84 | of it, either verbatim or with modifications and/or translated into 85 | another language. (Hereinafter, translation is included without limitation 86 | in the term modification.) Each licensee is addressed as 87 | you. 88 | 89 | Activities other than copying, distribution and modification are not 90 | covered by this License; they are outside its scope. The act of running 91 | the Program is not restricted, and the output from the Program is covered 92 | only if its contents constitute a work based on the Program (independent 93 | of having been made by running the Program). Whether that is true depends 94 | on what the Program does. 95 | 96 | Section 1 97 | 98 | You may copy and distribute verbatim copies of the Program's source 99 | code as you receive it, in any medium, provided that you conspicuously and 100 | appropriately publish on each copy an appropriate copyright notice and 101 | disclaimer of warranty; keep intact all the notices that refer to this 102 | License and to the absence of any warranty; and give any other recipients 103 | of the Program a copy of this License along with the Program. 104 | 105 | You may charge a fee for the physical act of transferring a copy, 106 | and you may at your option offer warranty protection in exchange for a 107 | fee. 108 | 109 | Section 2 110 | 111 | You may modify your copy or copies of the Program or any portion of 112 | it, thus forming a work based on the Program, and copy and distribute such 113 | modifications or work under the terms of Section 1 above, provided that 114 | you also meet all of these conditions: 115 | 116 | 117 | 118 | You must cause the modified files to carry prominent notices 119 | stating that you changed the files and the date of any change. 120 | 121 | 122 | 123 | You must cause any work that you distribute or publish, that in 124 | whole or in part contains or is derived from the Program or any part 125 | thereof, to be licensed as a whole at no charge to all third parties 126 | under the terms of this License. 127 | 128 | 129 | 130 | If the modified program normally reads commands interactively 131 | when run, you must cause it, when started running for such interactive 132 | use in the most ordinary way, to print or display an announcement 133 | including an appropriate copyright notice and a notice that there is 134 | no warranty (or else, saying that you provide a warranty) and that 135 | users may redistribute the program under these conditions, and telling 136 | the user how to view a copy of this License. (Exception: If the 137 | Program itself is interactive but does not normally print such an 138 | announcement, your work based on the Program is not required to print 139 | an announcement.) 140 | 141 | 142 | 143 | These requirements apply to the modified work as a whole. If 144 | identifiable sections of that work are not derived from the Program, and 145 | can be reasonably considered independent and separate works in themselves, 146 | then this License, and its terms, do not apply to those sections when you 147 | distribute them as separate works. But when you distribute the same 148 | sections as part of a whole which is a work based on the Program, the 149 | distribution of the whole must be on the terms of this License, whose 150 | permissions for other licensees extend to the entire whole, and thus to 151 | each and every part regardless of who wrote it. 152 | 153 | Thus, it is not the intent of this section to claim rights or 154 | contest your rights to work written entirely by you; rather, the intent is 155 | to exercise the right to control the distribution of derivative or 156 | collective works based on the Program. 157 | 158 | In addition, mere aggregation of another work not based on the 159 | Program with the Program (or with a work based on the Program) on a volume 160 | of a storage or distribution medium does not bring the other work under 161 | the scope of this License. 162 | 163 | Section 3 164 | 165 | You may copy and distribute the Program (or a work based on it, 166 | under Section 2 in object code or executable form under the terms of 167 | Sections 1 and 2 above provided that you also do one of the 168 | following: 169 | 170 | 171 | 172 | Accompany it with the complete corresponding machine-readable 173 | source code, which must be distributed under the terms of Sections 1 174 | and 2 above on a medium customarily used for software interchange; 175 | or, 176 | 177 | 178 | 179 | Accompany it with a written offer, valid for at least three 180 | years, to give any third party, for a charge no more than your cost of 181 | physically performing source distribution, a complete machine-readable 182 | copy of the corresponding source code, to be distributed under the 183 | terms of Sections 1 and 2 above on a medium customarily used for 184 | software interchange; or, 185 | 186 | 187 | 188 | Accompany it with the information you received as to the offer 189 | to distribute corresponding source code. (This alternative is allowed 190 | only for noncommercial distribution and only if you received the 191 | program in object code or executable form with such an offer, in 192 | accord with Subsection b above.) 193 | 194 | 195 | 196 | The source code for a work means the preferred form of the work for 197 | making modifications to it. For an executable work, complete source code 198 | means all the source code for all modules it contains, plus any associated 199 | interface definition files, plus the scripts used to control compilation 200 | and installation of the executable. However, as a special exception, the 201 | source code distributed need not include anything that is normally 202 | distributed (in either source or binary form) with the major components 203 | (compiler, kernel, and so on) of the operating system on which the 204 | executable runs, unless that component itself accompanies the 205 | executable. 206 | 207 | If distribution of executable or object code is made by offering 208 | access to copy from a designated place, then offering equivalent access to 209 | copy the source code from the same place counts as distribution of the 210 | source code, even though third parties are not compelled to copy the 211 | source along with the object code. 212 | 213 | Section 4 214 | 215 | You may not copy, modify, sublicense, or distribute the Program 216 | except as expressly provided under this License. Any attempt otherwise to 217 | copy, modify, sublicense or distribute the Program is void, and will 218 | automatically terminate your rights under this License. However, parties 219 | who have received copies, or rights, from you under this License will not 220 | have their licenses terminated so long as such parties remain in full 221 | compliance. 222 | 223 | Section 5 224 | 225 | You are not required to accept this License, since you have not 226 | signed it. However, nothing else grants you permission to modify or 227 | distribute the Program or its derivative works. These actions are 228 | prohibited by law if you do not accept this License. Therefore, by 229 | modifying or distributing the Program (or any work based on the Program), 230 | you indicate your acceptance of this License to do so, and all its terms 231 | and conditions for copying, distributing or modifying the Program or works 232 | based on it. 233 | 234 | Section 6 235 | 236 | Each time you redistribute the Program (or any work based on the 237 | Program), the recipient automatically receives a license from the original 238 | licensor to copy, distribute or modify the Program subject to these terms 239 | and conditions. You may not impose any further restrictions on the 240 | recipients' exercise of the rights granted herein. You are not responsible 241 | for enforcing compliance by third parties to this License. 242 | 243 | Section 7 244 | 245 | If, as a consequence of a court judgment or allegation of patent 246 | infringement or for any other reason (not limited to patent issues), 247 | conditions are imposed on you (whether by court order, agreement or 248 | otherwise) that contradict the conditions of this License, they do not 249 | excuse you from the conditions of this License. If you cannot distribute 250 | so as to satisfy simultaneously your obligations under this License and 251 | any other pertinent obligations, then as a consequence you may not 252 | distribute the Program at all. For example, if a patent license would not 253 | permit royalty-free redistribution of the Program by all those who receive 254 | copies directly or indirectly through you, then the only way you could 255 | satisfy both it and this License would be to refrain entirely from 256 | distribution of the Program. 257 | 258 | If any portion of this section is held invalid or unenforceable 259 | under any particular circumstance, the balance of the section is intended 260 | to apply and the section as a whole is intended to apply in other 261 | circumstances. 262 | 263 | It is not the purpose of this section to induce you to infringe any 264 | patents or other property right claims or to contest validity of any such 265 | claims; this section has the sole purpose of protecting the integrity of 266 | the free software distribution system, which is implemented by public 267 | license practices. Many people have made generous contributions to the 268 | wide range of software distributed through that system in reliance on 269 | consistent application of that system; it is up to the author/donor to 270 | decide if he or she is willing to distribute software through any other 271 | system and a licensee cannot impose that choice. 272 | 273 | This section is intended to make thoroughly clear what is believed 274 | to be a consequence of the rest of this License. 275 | 276 | Section 8 277 | 278 | If the distribution and/or use of the Program is restricted in 279 | certain countries either by patents or by copyrighted interfaces, the 280 | original copyright holder who places the Program under this License may 281 | add an explicit geographical distribution limitation excluding those 282 | countries, so that distribution is permitted only in or among countries 283 | not thus excluded. In such case, this License incorporates the limitation 284 | as if written in the body of this License. 285 | 286 | Section 9 287 | 288 | The Free Software Foundation may publish revised and/or new versions 289 | of the General Public License from time to time. Such new versions will be 290 | similar in spirit to the present version, but may differ in detail to 291 | address new problems or concerns. 292 | 293 | Each version is given a distinguishing version number. If the 294 | Program specifies a version number of this License which applies to it and 295 | any later version, you have the option of following the 296 | terms and conditions either of that version or of any later version 297 | published by the Free Software Foundation. If the Program does not specify 298 | a version number of this License, you may choose any version ever 299 | published by the Free Software Foundation. 300 | 301 | Section 10 302 | 303 | If you wish to incorporate parts of the Program into other free 304 | programs whose distribution conditions are different, write to the author 305 | to ask for permission. For software which is copyrighted by the Free 306 | Software Foundation, write to the Free Software Foundation; we sometimes 307 | make exceptions for this. Our decision will be guided by the two goals of 308 | preserving the free status of all derivatives of our free software and of 309 | promoting the sharing and reuse of software generally. 310 | 311 | NO WARRANTY Section 11 312 | 313 | BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 314 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 315 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 316 | PROVIDE THE PROGRAM AS IS WITHOUT WARRANTY OF ANY KIND, 317 | EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 318 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 319 | ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. 320 | SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY 321 | SERVICING, REPAIR OR CORRECTION. 322 | 323 | Section 12 324 | 325 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 326 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 327 | AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 328 | DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 329 | DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING 330 | BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR 331 | LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO 332 | OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS 333 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 334 | 335 | END OF TERMS AND CONDITIONS 336 | 337 | How to Apply These Terms to Your New 338 | Programs 339 | 340 | If you develop a new program, and you want it to be of the greatest 341 | possible use to the public, the best way to achieve this is to make it 342 | free software which everyone can redistribute and change under these 343 | terms. 344 | 345 | To do so, attach the following notices to the program. It is safest 346 | to attach them to the start of each source file to most effectively convey 347 | the exclusion of warranty; and each file should have at least the 348 | copyright line and a pointer to where the full notice is 349 | found. 350 | 351 | <one line to give the program's name and a brief idea of what it 352 | does.> Copyright (C) <year> <name of author> 353 | 354 | This program is free software; you can redistribute it and/or modify 355 | it under the terms of the GNU General Public License as published by the 356 | Free Software Foundation; either version 2 of the License, or (at your 357 | option) any later version. 358 | 359 | This program is distributed in the hope that it will be useful, but 360 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 361 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 362 | for more details. 363 | 364 | You should have received a copy of the GNU General Public License 365 | along with this program; if not, write to the Free Software Foundation, 366 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 367 | 368 | Also add information on how to contact you by electronic and paper 369 | mail. 370 | 371 | If the program is interactive, make it output a short notice like 372 | this when it starts in an interactive mode: 373 | 374 | Gnomovision version 69, Copyright (C) year name of author 375 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type 376 | show w. This is free software, and you are welcome to 377 | redistribute it under certain conditions; type show c for 378 | details. 379 | 380 | The hypothetical commands show w and show 381 | c should show the appropriate parts of the General Public License. 382 | Of course, the commands you use may be called something other than 383 | show w and show c; they could even be 384 | mouse-clicks or menu items--whatever suits your program. 385 | 386 | You should also get your employer (if you work as a programmer) or 387 | your school, if any, to sign a copyright disclaimer for the 388 | program, if necessary. Here is a sample; alter the names: 389 | 390 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 391 | program Gnomovision (which makes passes at compilers) 392 | written by James Hacker. 393 | 394 | <signature of Ty Coon>, 1 April 1989 Ty Coon, President of 395 | Vice 396 | 397 | This General Public License does not permit incorporating your 398 | program into proprietary programs. If your program is a subroutine 399 | library, you may consider it more useful to permit linking proprietary 400 | applications with the library. If this is what you want to do, use the GNU 401 | Library General Public License instead of this License. 402 | -------------------------------------------------------------------------------- /sections/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 19 | Modules 20 | 21 | Modules allow the display of relatively small snippets of information 22 | in the front– or backend of a Joomla! site. 23 | 24 |
25 | Legacy vs Joomla 4 modules 26 | 27 | Modules are the oldest extension type in Joomla. It was the first 28 | ever extension type added to Mambo, Joomla's predecessor, back in the 29 | early 2000s. 30 | 31 | Modules had remain largely unchanged ever since, with the exception 32 | of a few additions (like support for view templates) over the course of 33 | Joomla! 1.5. It should be no surprise that modules were thoroughly 34 | rethought in Joomla 4. After all, a 20-year-old concept does need a big 35 | kick to bring it up to speed with modern development standards. 36 | 37 |
38 | Legacy modules (Joomla 1.x to 3.x) 39 | 40 | In its purest and most traditional form, a module consists of an 41 | XML manifest file and a PHP file which outputs content, plus the 42 | language file. Let's take a minimal site module as an example. The 43 | manifest file example.xml looks like this: 44 | 45 | <?xml version="1.0" encoding="utf-8"?> 46 | <extension type="module" method="upgrade" client="site"> 47 | <name>MOD_EXAMPLE</name> 48 | <author>Acme Corp.</author> 49 | <creationDate>2023-08-16</creationDate> 50 | <copyright>Copyright (c)2023 Acme Cord</copyright> 51 | <license>GNU GPL v3 or later</license> 52 | <authorEmail>acme@example.com</authorEmail> 53 | <authorUrl>www.example.com</authorUrl> 54 | <version>1.0.0</version> 55 | <description>MOD_EXAMPLE_XML_DESC</description> 56 | <files> 57 | <file module="mod_example">mod_example.php</file> 58 | </files> 59 | <languages folder="language"> 60 | <language tag="en-GB">en-GB/en-GB.mod_example.sys.ini</language> 61 | </languages> 62 | 63 | <config addfieldpath="/administrator/components/com_ats/fields"> 64 | <fields name="params"> 65 | <fieldset name="advanced"> 66 | <field 67 | name="moduleclass_sfx" 68 | type="textarea" 69 | rows="3" 70 | label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL" 71 | description="COM_MODULES_FIELD_MODULECLASS_SFX_DESC" /> 72 | 73 | <field 74 | name="cache" 75 | type="list" 76 | default="1" 77 | label="COM_MODULES_FIELD_CACHING_LABEL" 78 | description="COM_MODULES_FIELD_CACHING_DESC" 79 | > 80 | <option value="1">JGLOBAL_USE_GLOBAL</option> 81 | <option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option> 82 | </field> 83 | 84 | <field 85 | name="cache_time" 86 | type="text" 87 | default="900" 88 | label="COM_MODULES_FIELD_CACHE_TIME_LABEL" 89 | description="COM_MODULES_FIELD_CACHE_TIME_DESC" /> 90 | 91 | <field 92 | name="cachemode" 93 | type="hidden" 94 | default="static"> 95 | <option value="static"></option> 96 | </field> 97 | </fieldset> 98 | </fields> 99 | </config> 100 | </extension> 101 | 102 | The module configuration you see above is pretty much boilerplate. 103 | It lets com_modules (the built-in component which manages modules) to 104 | display standard module controls such as the module class suffix, and 105 | caching options 106 | Why do you have to add this boilerplate yourself instead of 107 | com_modules always showing it? Good question! My working theory 108 | —since nobody seems to know for sure— is that it was the “easiest” 109 | way to let developers decide if they should offer caching options, 110 | what is the default caching time, and whether they want to allow 111 | alternate view templates. Of course, these 112 | could have been attributes under a different 113 | key in the XML manifest, avoiding all the annoying boilerplate. I am 114 | just annoyed by boilerplate when it can be avoided, I guess. 115 | . 116 | 117 | The module file, mod_example.php, is dead 118 | simple in its simplest form: 119 | 120 | <?php 121 | defined('_JEXEC') || die; 122 | ?> 123 | Hello, world! 124 | 125 | Adding view templates 126 | 127 | Of course, modules are rarely this simple. They probably need to 128 | do some kind of processing e.g. talk to a component to get some data to 129 | display. While you could intermix display and logic 130 | in the module file —as was the case in the olden days of Joomla 1.x/2.x— 131 | this causes a pretty obvious problem for site integrators. They cannot 132 | override the module's display. For this reason, the concept of view 133 | templates was introduced in modules during the Joomla! 1.5 lifecycle. 134 | This requires two changes. 135 | 136 | First, we need to add one more option, layout, to the 137 | advanced fieldset of the XML manifest: 138 | 139 | <field 140 | name="layout" 141 | type="modulelayout" 142 | label="JFIELD_ALT_LAYOUT_LABEL" 143 | description="JFIELD_ALT_MODULE_LAYOUT_DESC" 144 | validate="moduleLayout" 145 | /> 146 | 147 | Then, we need to change our module file to use 148 | \Joomla\CMS\Helper\ModuleHelper::getLayoutPath 149 | to get the filesystem path of the view template to load: 150 | 151 | <?php 152 | defined('_JEXEC') || die; 153 | ?> 154 | require_once \Joomla\CMS\Helper\ModuleHelper::getLayoutPath('mod_example', $params->get('layout', 'default'); 155 | 156 | The view templates are loaded from your module's 157 | tmpl directory. In the example above, the default 158 | view template is default.php. 159 | 160 | If you're wondering where $params came from: this is 161 | a \Joomla\Registry\Registry object holding your 162 | module's configuration data. It is automatically passed by Joomla! to 163 | your module. 164 | 165 | Since we added a folder, we need to add it to the XML manifest as 166 | well: 167 | 168 | <folder>tmpl</folder> 169 | 170 | Adding a Helper 171 | 172 | Using a view template is an indubitably better approach than 173 | mixing logic and presentation code in the module. However, it still 174 | makes for a really miserable developer experience since you have raw 175 | code running inside a context which is not under your control. The 176 | function and variable names you use might end up 177 | conflicting with those added in future versions of Joomla!, leading to 178 | hilarious and hard to troubleshoot problems with your plugin. 179 | 180 | This is why the concept of module helpers was 181 | introduced to Joomla. In classic modules this is just an abstract class 182 | with static methods you include from your module code. All your 183 | executable code is put there. Look at any core module in Joomla! 3.10 to 184 | see how it's done. 185 |
186 | 187 |
188 | Joomla 4 modules 189 | 190 | Even with view templates and helpers, the classic modules are 191 | still a bit of a mess from a developer's point of view. You still have 192 | that ugly module entry point file which executes under an arbitrary 193 | context. There is still a lot of room for bugs because of function and 194 | variable names conflicts. Moreover, you can't make use of any service 195 | providers which, as we have discussed, are the lifeblood of Joomla's 196 | architecture from Joomla 4 onwards. 197 | 198 | To this end, modules were rethought in Joomla! 4. 199 | 200 | There is no longer a module entry point file. Instead, you have a 201 | Dispatcher class. You override the Dispatcher's 202 | getLayoutData method to return an array with 203 | data that can be displayed by your module's view templates. This is a 204 | complete replacement to the module entry point file. Since it's a class 205 | instantiated by Joomla, the execution is isolated in its own context, 206 | therefore preventing any issues with function and variable 207 | naming. 208 | 209 | The Dispatcher automatically loads the correct view template file 210 | and passes it the data returned from 211 | getLayoutData as variables 212 | (it runs extract() 213 | on the array of data). 214 | 215 | 216 | This is the big change from Joomla 3.x and earlier. 217 | 218 | In older versions of Joomla! you could have your module's view 219 | template pull data from the module's helper by 220 | calling the helper's static methods. This is no longer the 221 | case. 222 | 223 | In Joomla! 4 and later it is the Dispatcher which calls the 224 | (non-static!) methods of the helper object. Then, it 225 | pushes the data to the view template. 226 | 227 | Once you understand the difference between pulling data and 228 | pushing data the whole concept of modules under Joomla 4 and later 229 | becomes crystal clear. 230 | 231 | 232 | The presence of a Helper class is assumed. All you have to do is 233 | tell Joomla what it's called in your module's service provider file. 234 | 235 | 236 | 237 | Unlike Joomla 3.x and earlier, the module's helper no longer has 238 | static methods. It has regular, non-static methods. When you need to 239 | use the helper in your Dispatcher you will be given an instantiated 240 | object. 241 | 242 | This is deliberate. You cannot push services, like the database 243 | object, to a class (at least not without violating several good 244 | software design principles). You can trivially do so in objects which 245 | implement some of the handy Interfaces and use some of the handy 246 | Traits provided by Joomla. We'll see how that works a bit 247 | later. 248 | 249 | 250 | Of course, all executable PHP code is namespaced — just like with 251 | all Joomla 4 and later native extensions. 252 | 253 | This may sound like a lot of work, but it's really not 254 | that bad. In the past you'd create the XML 255 | manifest, the language file, your module entry point, your helper, and 256 | your view template, in this order. With Joomla 4 and alter you create 257 | the XML manifest, the language file, the service locator, the 258 | dispatcher, your helper, and your view template, in this order. The 259 | service locator is just boilerplate. Essentially, you are replacing the 260 | module entry point with a bit of boilerplace (service locator) and an 261 | overridden method in your Dispatcher. Everything else is the same. It 262 | only sounds hard because it's different, not because it is any 263 | harder. 264 | 265 | So, here's our XML manifest file: 266 | 267 | <?xml version="1.0" encoding="utf-8"?> 268 | <extension type="module" method="upgrade" client="site"> 269 | <name>MOD_EXAMPLE</name> 270 | <author>Acme Corp.</author> 271 | <creationDate>2023-08-16</creationDate> 272 | <copyright>Copyright (c)2023 Acme Cord</copyright> 273 | <license>GNU GPL v3 or later</license> 274 | <authorEmail>acme@example.com</authorEmail> 275 | <authorUrl>www.example.com</authorUrl> 276 | <version>1.0.0</version> 277 | <description>MOD_EXAMPLE_XML_DESC</description> 278 | <namespace path="src">Acme\Module\Example</namespace> 279 | <files> 280 | <folder module="mod_example">services</folder> 281 | <folder>src</folder> 282 | <folder>tmpl</folder> 283 | </files> 284 | <languages folder="language"> 285 | <language tag="en-GB">en-GB/en-GB.mod_example.sys.ini</language> 286 | </languages> 287 | 288 | <config addfieldpath="/administrator/components/com_ats/fields"> 289 | <fields name="params"> 290 | <fieldset name="advanced"> 291 | <field 292 | name="layout" 293 | type="modulelayout" 294 | label="JFIELD_ALT_LAYOUT_LABEL" 295 | class="form-select" 296 | validate="moduleLayout" 297 | /> 298 | 299 | <field 300 | name="moduleclass_sfx" 301 | type="textarea" 302 | rows="3" 303 | label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL" 304 | description="COM_MODULES_FIELD_MODULECLASS_SFX_DESC" /> 305 | 306 | <field 307 | name="cache" 308 | type="list" 309 | default="1" 310 | label="COM_MODULES_FIELD_CACHING_LABEL" 311 | description="COM_MODULES_FIELD_CACHING_DESC" 312 | > 313 | <option value="1">JGLOBAL_USE_GLOBAL</option> 314 | <option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option> 315 | </field> 316 | 317 | <field 318 | name="cache_time" 319 | type="text" 320 | default="900" 321 | label="COM_MODULES_FIELD_CACHE_TIME_LABEL" 322 | description="COM_MODULES_FIELD_CACHE_TIME_DESC" /> 323 | 324 | <field 325 | name="cachemode" 326 | type="hidden" 327 | default="static"> 328 | <option value="static"></option> 329 | </field> 330 | </fieldset> 331 | </fields> 332 | </config> 333 | </extension> 334 | 335 | The text is bold is the additions / changes for Joomla! 4 and 336 | later versions. 337 |
338 |
339 | 340 |
341 | Service provider 342 | 343 | As with all native extensions since Joomla 4, modules have a service 344 | provider named provider.php in their 345 | services directory. The purpose of this provide is to 346 | tell Joomla where to find the module's dispatcher, and register the 347 | module's helper as a service. 348 | 349 | It's just a bit of boilerplate code, like this: 350 | 351 | <?php 352 | defined('_JEXEC') || die; 353 | 354 | use Joomla\CMS\Extension\Service\Provider\HelperFactory; 355 | use Joomla\CMS\Extension\Service\Provider\Module; 356 | use Joomla\CMS\Extension\Service\Provider\ModuleDispatcherFactory; 357 | use Joomla\DI\Container; 358 | use Joomla\DI\ServiceProviderInterface; 359 | 360 | return new class () implements ServiceProviderInterface { 361 | public function register(Container $container) 362 | { 363 | $container->registerServiceProvider(new ModuleDispatcherFactory('\\Acme\\Module\\Example')); 365 | $container->registerServiceProvider(new HelperFactory('\\Acme\\Module\\Example\\Site\\Helper')); 367 | 368 | $container->registerServiceProvider(new Module()); 369 | } 370 | }; 371 | 372 | 373 | There are really two things you need to take note of here. 374 | 375 | The argument to the 376 | Joomla\CMS\Extension\Service\Provider\ModuleDispatcherFactory's 377 | constructor is the namespace of the module without the Site or 378 | Administrator part. In other words, it is exactly what you put in your XML 379 | manifest. Joomla knows to add the Site (frontend modules) or Administrator 380 | (backend modules) to the namespace, and look for 381 | Dispatcher\Dispatcher under it. In other words, in 382 | the example frontend module we have here, the Dispatcher class is 383 | understood to be 384 | Acme\Module\Example\Site\Dispatcher\Dispatcher. 385 | 386 | 387 | Remember! A module always needs a Dispatcher. 388 | This is where you tell Joomla what data to send to the module's view 389 | template for display. If you were to not implement a Dispatcher you 390 | would have nothing useful to display. 391 | 392 | This is the big change from Joomla 3.x and earlier. It is no 393 | longer possible to pull data in the view template 394 | from the module helper directly. It is always 395 | pushed to the module. 396 | 397 | 398 | The argument to the 399 | Joomla\CMS\Extension\Service\Provider\HelperFactory's 400 | constructor, however, is a fully qualified namespace to the module's 401 | Helper classes. This means that it's the namespace you put in your XML 402 | manifest, plus Site (frontend modules) or Administrator, plus Helper. In 403 | other words, in the example frontend module we have here, the helper 404 | classes' namespace is 405 | Acme\Module\Example\Site\Helper. 406 | 407 | The HelperFactory does a modicum of "magic" when instantiating your 408 | helper classes. It checks which interfaces they implement and pushes the 409 | respective services to them. At the time of this writing, it checks if the 410 | helper class implements the 411 | Joomla\Database\DatabaseAwareInterface 412 | interface and pushes the database object to the instantiated helper object 413 | using the interface's setDatabase method. 414 | 415 | If you want to push custom services to your helpers you need to 416 | subclass the 417 | Joomla\CMS\Extension\Service\Provider\HelperFactory 418 | class and use your custom helper factory instead of Joomla's in your 419 | service provider. Unfortunately, merely extending the service does not 420 | work as expected (there's been a long discussion we've already had in the 421 | Joomla! GitHub Issues about it). 422 |
423 | 424 |
425 | Dispatcher class 426 | 427 | The Dispatcher is the "brains" of the module. Its 428 | getLayoutData method is called every time the 429 | module is rendered. It returns an array with the data which will be 430 | displayed by the view templates of the module. 431 | 432 | A minimal implementation would look like this: 433 | 434 | <?php 435 | 436 | namespace Acme\Module\Example\Site\Dispatcher; 437 | 438 | defined('_JEXEC') || die; 439 | 440 | use Joomla\CMS\Dispatcher\AbstractModuleDispatcher; 441 | use Joomla\CMS\Helper\HelperFactoryAwareInterface; 442 | use Joomla\CMS\Helper\HelperFactoryAwareTrait; 443 | 444 | class Dispatcher extends AbstractModuleDispatcher implements HelperFactoryAwareInterface 445 | { 446 | use HelperFactoryAwareTrait; 447 | 448 | protected function getLayoutData() 449 | { 450 | $data = parent::getLayoutData(); 451 | 452 | $data['stuff'] = $this->getHelperFactory() 453 | ->getHelper('ExampleHelper') 454 | ->getStuff($data['params'], $this->getApplication()); 455 | 456 | return $data; 457 | } 458 | } 459 | 460 | 461 | Let's focus on the overridden getLayoutData 462 | method. 463 | 464 | We must always call the parent (overridden) method first. This gives 465 | us an array with very important bits of information needed to render the 466 | module: 467 | 468 | 469 | 470 | module. The raw object with the module information 471 | as stored in the database. 472 | 473 | 474 | 475 | app. The Joomla! application object. Do NOT assume 476 | it's always an instance of SiteApplication or 477 | AdministratorApplication; check! 478 | 479 | 480 | 481 | input. The Joomla! input object. Use it wisely. If 482 | you are depending on request parameters for display of your module you 483 | need to consider how this affects caching, and whether having a 484 | component might be a better fit for your use case. 485 | 486 | 487 | 488 | params. A Registry object with the module's 489 | parameters. 490 | 491 | 492 | 493 | template. The name of the Joomla! template used to 494 | render the page. This is equivalent to calling 495 | \Joomla\CMS\Factory::getApplication()->getTemplate(). 496 | 497 | 498 | 499 | This data must always be present for Joomla! to successfully render 500 | a module. Therefore, we need to add to it. That's why 501 | we add a new key to the array before returning it. 502 | 503 | We see that we call 504 | $this->getHelperFactory()->getHelper('ExampleHelper'). 505 | As you might have inferred, this tells Joomla to create an object instance 506 | of the ExampleHelper class in the module's helper namespace. As you may 507 | recall, we registered that namespace in our service provider. In the 508 | example plugin, the class we're asking Joomla to instantiate is 509 | Acme\Module\Example\Site\Helper\ExampleHelper. 510 | 511 | 512 | We have to stress out that this is a major change from Joomla! 3.x 513 | and earlier. We no longer call static methods in the helper class. We 514 | have Joomla! create an object instance of that class and call its 515 | non-static method directly. 516 | 517 | 518 | The method calls also shows a way to pass the module parameters to 519 | your helper object: by passing $data['params']. As noted 520 | above, the data element contains a Registry object with the module 521 | parameters. 522 | 523 | The other thing you see in that method call is how you can pass the 524 | Joomla Application object to your helpers: by sending 525 | $this->app (or $data['app']) as an argument. 526 | This is preferred to going through the 527 | Joomla\CMS\Factory class as it makes Unit Testing 528 | of your module easier. 529 | 530 | Even if you don't do any unit testing, it's always a good idea to 531 | inject dependencies (e.g. sending them as arguments, 532 | or otherwise setting them on the target object) instead of pulling 533 | dependencies by calling static methods. In practice, you will see that 534 | some core Joomla services, such as the UserFactory) are not readily 535 | available for injection, breaking this golden rule. This is something 536 | that's been actively worked on in Joomla!. Eventually, it will be possible 537 | to do dependency injection for all core services. 538 | 539 | Needless to say, you can have more than one data keys for display in 540 | your module. Just remember, the $data array you return will 541 | be extracted into variables. Therefore, you must use array key names which 542 | are valid PHP variable names. 543 |
544 | 545 |
546 | Language files 547 | 548 | Language files in modules on Joomla! 4 and later versions follow the 549 | same concept as all other language files, e.g. for components: they no longer have the language 551 | tag as a prefix. 552 | 553 | In Joomla! 3.x and earlier versions you would have two language 554 | files for English (Great Britain): 555 | 556 | 557 | 558 | en-GB.mod_example.ini for the language 559 | strings you use when rendering the module, and the language strings in 560 | your module's configuration parameters. 561 | 562 | 563 | 564 | en-GB.mod_example.sys.ini for the language 565 | strings used in your XML manifest file for the module's name and 566 | description. 567 | 568 | 569 | 570 | In Joomla! 4 and later versions they are now called: 571 | 572 | 573 | 574 | mod_example.ini 575 | 576 | 577 | 578 | mod_example.sys.ini 579 | 580 | 581 | 582 | Module language files are loaded automatically. You do not need to 583 | load them yourself. 584 |
585 | 586 |
587 | The Helper 588 | 589 | In Joomla 3 and earlier versions the module helper was a class with 590 | static methods. You would call these static methods in the module's entry 591 | point file, or a module view template, directly. This is the concept of 592 | pulling information. 593 | 594 | The big limitation of this concept is that static method calls are 595 | inflexible. If you are trying to write any kind of tests for your view 596 | templates, you will quickly find that the static calls make your code 597 | untestable unless you go to great lengths (create a mock class, create a 598 | stream wrapper, load the PHP code, replace the calls to the helper with 599 | calls to the mock class, and test the temporary file you created in the 600 | stream wrapper). This is why this concept, while easy to use by novice 601 | developers, is no longer considered a good practice — and that applies in 602 | general in programming, not just Joomla! modules. 603 | 604 | As noted earlier, Joomla 4 introduced a different concept, one where 605 | you push information to the view template through the 606 | Dispatcher. This isolates the business logic from the presentation. When 607 | you, or a site integrator, create a view template or view template 608 | override for a module you no longer need to care how 609 | you will get the data you need to display. From your point of view, the 610 | display data is magically there. From a developer's point of view, the 611 | isolation of business logic and presentation means that both are perfectly 612 | testable; the former with Unit Tests, the latter by passing a set of 613 | hard-coded data and inspecting the generated output. 614 | 615 | In practical terms, you no longer have static methods. You have 616 | regular methods. Your class is no longer abstract; it's just a regular 617 | class. 618 | 619 | The simplest helper class you can have is like this: 620 | 621 | <?php 622 | 623 | namespace Acme\Module\Example\Site\Helper; 624 | 625 | defined('_JEXEC') || die; 626 | 627 | class ExampleHelper 628 | { 629 | public function getStuff(): string 630 | { 631 | return "Hello, world."; 632 | } 633 | } 634 | 635 | In your Dispatcher, you'd call this as 636 | $this->getHelperFactory()->getHelper('ExampleHelper')->getStuff();. 637 | 638 | In practice, you will need access to some database date. In the past 639 | you'd get Joomla's database object by doing something like $db = 640 | \Joomla\CMS\Factory::getDbo();. This is no longer the case. You 641 | will just implement Joomla's 642 | \Joomla\Database\DatabaseAwareInterface in 643 | your class and use Joomla's 644 | \Joomla\Database\DatabaseAwareTrait trait. You then 645 | get the database object with $db = 646 | $this->getDatabase();. 647 | 648 | <?php 649 | 650 | namespace Acme\Module\Example\Site\Helper; 651 | 652 | defined('_JEXEC') || die; 653 | 654 | use Joomla\Database\DatabaseAwareInterface; 655 | use Joomla\Database\DatabaseAwareTrait; 656 | 657 | class ExampleHelper implements DatabaseAwareInterface 658 | { 659 | use DatabaseAwareTrait; 660 | 661 | public function getStuff(): string 662 | { 663 | $db = $this->getDatabase(); 664 | 665 | // Do some database stuff here. 666 | 667 | return "Hello, world."; 668 | } 669 | } 670 | 671 | 672 | “How does this sorcery work?” you wonder. When you instantiate the 673 | helper object through the helper factory, it checks if your class 674 | implements the DatabaseAwareInterface. If it does, it pushes the Joomla! 675 | database object to the helper object. That's why you can retrieve it 676 | with $this->getDatabase() without having written code to 677 | push it yourself. 678 | 679 | 680 | If you need to push any other object, including the module 681 | parameters, you have to do it with method parameters. We showed that when 682 | talking about the Dispatcher. So let's see how we can pass the module 683 | parameters and the application object to the helper: 684 | 685 | <?php 686 | 687 | namespace Acme\Module\Example\Site\Helper; 688 | 689 | defined('_JEXEC') || die; 690 | 691 | use Joomla\CMS\Application\CMSApplicationInterface; 692 | use Joomla\CMS\Application\SiteApplication; 693 | use Joomla\Database\DatabaseAwareInterface; 694 | use Joomla\Database\DatabaseAwareTrait; 695 | use Joomla\Registry\Registry; 696 | 697 | class ExampleHelper implements DatabaseAwareInterface 698 | { 699 | use DatabaseAwareTrait; 700 | 701 | public function getStuff(Registry $config, CMSApplicationInterface $app): string 702 | { 703 | if (!$app instanceof SiteApplication) { 704 | return ''; 705 | } 706 | 707 | $db = $this->getDatabase(); 708 | 709 | // Do some database stuff here. 710 | 711 | return sprintf("Hello, %s.", $config->get('name', 'world')); 712 | } 713 | } 714 | 715 | As a reminder, here's how this was called from the 716 | Dispatcher: 717 | 718 | $data['stuff'] = $this->getHelperFactory() 719 | ->getHelper('ExampleHelper') 720 | ->getStuff($data['params'], $this->getApplication()); 721 | 722 | As you can see, it is fairly easy, as long as you remember to 723 | push information to the helper instead of the old way 724 | of having it pull information from static 725 | methods. 726 |
727 | 728 |
729 | View templates 730 | 731 | Modules need to be able to display information in a human-readable 732 | manner, in HTML — this is their only purpose in life. The Helper handles 733 | all the business logic to produce this data, and the Dispatcher pushes it 734 | to our view template which renders it as HTML. 735 | 736 | The view templates are placed in the tmpl 737 | folder of your module. 738 | 739 | The concept is not unlike Components themselves, with a few twists. 740 | The most obvious twist is that a module's view template always produces HTML. The second twist is how we 742 | get our display data: as “magically” appearing variables. 743 | 744 | To refresh your memory, the Dispatcher's 745 | getLayoutData method returns an array. Joomla! 746 | puts that array through PHP's extract() function before loading our view 747 | template. 748 |
749 | 750 |
751 | Modules and com_ajax 752 | 753 | Sometimes, you need to have your modules return data asynchronously 754 | to the HTML page rendering, using client-side (JavaScript) code. DO NOT 755 | use arbitrarily named .php files which will be accessed directly over the 756 | web; this is a terrible and insecure practice. The best way to do that is 757 | by using Joomla's com_ajax component. 758 | 759 | com_ajax is a special core component built into Joomla. By itself, 760 | it can't do much. Its job is to let non-component, first-class Joomla 761 | extension types (modules, plugins, and templates) handle requests and 762 | return results either as JSON or as any arbitrary format. 763 | 764 | For modules, you would need to load a URL like this: 765 | index.php?option=com_ajax&module=mod_example&method=something&format=raw. 766 | For backend modules you obviously need to use 767 | administrator/index.php. 768 | 769 | The way this works is that com_ajax will create an instance of the 770 | module's DIC (that is to say, use the code in our module's 771 | services/provider.php file), instantiate the helper 772 | that has the name 773 | ModulenameHelper, where 774 | Modulename is the name of our module without 775 | the mod_ prefix (e.g. Example for 776 | mod_example), and call the method 777 | MethodnameAjax where 778 | Methodname is the value of the 779 | method URL parameter. In the example above, it would load the 780 | ExampleHelper helper of mod_example 781 | and call its SomethingAjax method. 782 | 783 | If you use format=raw, one of the following will happen: 784 | 785 | 786 | 787 | If you throw an exception or return a Throwable, it will set the 788 | HTTP status to the throwable's status code and return a body similar 789 | to "RuntimeException:Your throwable's message". 790 | 791 | 792 | 793 | If you return a scalar (string, null, integer, float) it will 794 | return its string representation. 795 | 796 | 797 | 798 | If you return an object or array it will try to first cast it as 799 | an array, then implode() it into a string. This 800 | is quite useless, so please don't do that. 801 | 802 | 803 | 804 | If you use format=json it will try to convert your data to a JSON 805 | representation using Joomla's 806 | Joomla\CMS\Response\JsonResponse class. The 807 | returned JSON object has the following keys: 808 | 809 | 810 | 811 | success 812 | 813 | 814 | Boolean true if your method has neither thrown an exception, 815 | nor returned a Throwable. Boolean false otherwise. 816 | 817 | 818 | 819 | 820 | message 821 | 822 | 823 | Only when success is false. If your method threw an exception, 824 | or returned a Throwable object: the message of that throwable. 825 | Otherwise, this key is not set. 826 | 827 | 828 | 829 | 830 | messages 831 | 832 | 833 | Any enqueued Joomla! application messages. The messages are 834 | categorised by type, therefore they may be returned out of order. 835 | For example: 836 | 837 | messages: { 838 | "warning": [ 839 | "Some warning", 840 | "Another warning" 841 | ], 842 | "error": [ 843 | "The code went belly up. Whoopsie!" 844 | ] 845 | } 846 | 847 | 848 | 849 | 850 | data 851 | 852 | 853 | Only when success is true. The data returned by your 854 | method. 855 | 856 | 857 | 858 | 859 | Practical limitations 860 | 861 | com_ajax does not go through the module's Dispatcher. As a result, 862 | you do not have access to the module parameters, nor can you push any 863 | Joomla! object (such the application object, the input object, etc) to the 864 | Helper. 865 | 866 | If you need any module parameters to be used when handling an AJAX 867 | request you have to send them as part of the request (as GET or POST 868 | parameters), store them in the session, or pass the module's ID as part of 869 | the request (as a GET or POST parameter). Each method has limitations and 870 | security considerations: 871 | 872 | 873 | 874 | Passing configuration as GET or POST parameters is unsafe. Anyone can read them. Passing secrets, 876 | or filesystem paths, is detrimental to security. Moreover, any data 877 | read by this method must be ASSUMED 878 | to have been tampered with by a malicious actor who is trying to hack 879 | your site. Do not make any assumptions about data types, ranges, or 880 | that the data will even make any sense. For these reasons, using this 881 | method is VERY STRONGLY DISCOURAGED. 882 | 883 | 884 | 885 | Storing data in the session does not have the security 886 | considerations of passing data through GET or POST, but you must keep 887 | in mind that a user may try to open several pages at once, each one 888 | with a different instance of your module. This means that the data 889 | read from the session may be inconsistent and irrelevant to the 890 | current page. Depending on what your module does this could have 891 | security or privacy implications. 892 | 893 | 894 | 895 | Passing the numeric module ID is much safer. You can very easily 896 | try to load a module by that ID and determine if it exists, if it's 897 | published, and if the current user should be able to see it (access 898 | level check). You can then load its parameters into a Joomla Registry 899 | object and process data in your code. 900 | 901 | 902 | 903 | Generally speaking, having modules do AJAX is a problematic idea. 904 | While there are very few good use cases where this makes sense (and they 905 | all involve data which is always meant to be public), 906 | the majority of the uses cases I have seen in the real world display a 907 | blatant disregard for security and privacy. If you need to do complex 908 | processing maybe what you are doing does not belong in a module, but a 909 | component. 910 | 911 | And, please, PLEASE, do test your modules with 912 | use cases that involve multiple but differently configured instances of 913 | your module on the same page, or what happens if you open three or four 914 | pages with differently configured instances of your module in very quick 915 | succession (open all pages before the first AJAX request has the chance to 916 | be executed by the browser), ideally with users with different privileges 917 | logged in. You will be surprised at how many problems you will catch this 918 | way. 919 |
920 | 921 |
922 | Interfacing with your component (HMVC) 923 | 924 | 925 |
926 |
927 | -------------------------------------------------------------------------------- /sections/preface.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 21 | Introduction 22 | 23 |
24 | About this book 25 | 26 | I started writing this book in August 2022 as a quick reference 27 | for myself and other third party developers writing Joomla 4 extensions, 28 | or migrating our extensions to Joomla 4's native MVC. 29 | 30 | While Joomla 4 has an amazing, rich and powerful architecture and 31 | API it does not have any real developer-facing documentation. The 32 | documentation you will find is outdated, chaotic and leaves you running 33 | for your life. 34 | 35 | I am making every effort to make this book approachable to all 36 | levels of developers, from the novice who's barely hacked together their 37 | first plugin to the seasoned expert with dozens of extensions under 38 | their belt. However, to keep things relatively simple and because I am 39 | doing this unpaid, on my limited free time, I decided to take a few 40 | shortcuts here and there. I do not explain every concept in great 41 | detail, I try to explain it in practical detail. 42 | 43 | If you want to see what a real world Joomla extension looks like I 44 | urge you to take a look at and dissect the Joomla 4 extensions my 45 | company, Akeeba Ltd, has published free of charge. The simplest 46 | component to start with is Akeeba ContactUs. The most complete 47 | combination of a component, plugins and several modules we have 48 | published is Akeeba Ticket System — even the free of charge version uses 49 | most of the features I am describing in this book. 50 | 51 | Hopefully, you will find my approach pragmatic and result-driven 52 | instead of a dry, technical document. If you have suggestions for 53 | improvement or would like to sponsor this work feel free to contact me 54 | through the Contact Me page on dionysopoulos.me. 56 |
57 | 58 |
59 | About the author 60 | 61 | 62 | 63 | 64 | 65 | Hi, I am Nicholas. I am a Mechanical Engineer turned 66 | Software Engineer. I am from and still live in Greece with my wife, 67 | daughter and our two naughty cats. 68 | 69 | I've been into computers since I was 11 years olds, at the dawn of 70 | the 1990s. Back then dinosaurs were still walking among us, haircuts 71 | were weird, personal computers were the size of a 72 | small backpack and had far less computing power 73 | than your average smart lightbulb. Only one of the previous statements 74 | is false. I immediately took to programming for, as I said to my parents 75 | at the time, “I want to learn how to make this machine do things for me 76 | so I don't have to do them”. LIttle did I know what I was getting myself 77 | into… 78 | 79 | I've been using Joomla as a site integrator and extensions 80 | developer since it was called Mambo, back in 2004. I wrote my first 81 | mass-distributed extension called JoomlaPack in October 2006 while 82 | taking a two week break from my day job at the time as a business 83 | consultant. One thing led to another, JoomlaPack became Akeeba Backup 84 | and I gave up on business consultancy and mechanical engineering to 85 | become a full time software engineer. 86 | 87 | I've been actively participating in the Joomla community since 88 | 2009. I am a regular Joomla contributor and not just writing code. I've 89 | been involved in community outreach efforts and instigated the events 90 | leading to the beginning of the Joomla 4 effort. I still contribute to 91 | Joomla and, if I want to be honest with myself, I will continue doing 92 | that until Joomla or myself is no more, whichever comes first. 93 | 94 | I am neurodivergent (ADHD) and have a particular sense of humour. 95 | I firmly believe that life's too short to take it seriously. You'll see 96 | that a lot in this book. I don't care about writing a dry, boring book, 97 | especially on a subject as dry and boring as writing software. 98 |
99 | 100 |
101 | New Joomla 4 features at a glance 102 | 103 | Joomla 4 is a smorgasbord of new features, improvements and much 104 | needed changes. Unfortunately, a year into its release you'd be hard 105 | pressed to find any kind of documentation of what these are and how they 106 | can impact your software development practices. I will try to give you 107 | the 30,000-feet overview of what I found to be the 108 | most important changes. 109 | 110 | Namespaces. As you may remember, ever 112 | since Joomla 3.3 the legacy class names (e.g. JUri) changed 113 | to a namespaced equivalent (e.g. Joomla\CMS\Uri\Uri). In 114 | Joomla 4 a lot of the legacy classes stopped working. You can find out 115 | these changes neatly codified along with tools to mass convert your 116 | extensions in my Joomla Type 118 | Hints repository. In Joomla 4 the namespacing work went even 119 | deeper, having all classes in components, modules, plugins and templates 120 | also support namespaces — if you use the new, Joomla 4 API for 121 | developing extensions. This is a game-changer concept! Namespaced 122 | classes follow the PSR-4 124 | specification. Joomla caches and registers the PSR-4 mappings between 125 | namespace prefixes and directories on your site which means that 126 | you can safely use any class of any extension anywhere without 127 | having to use include or require ever 128 | again. This greatly reduces the possibility for bugs and 129 | massively improves the performance of Joomla and its extensions. 130 | 131 | Dependency Injection Container / Service 133 | Locator. Joomla 1.x to 3.x inclusive had this annoying 134 | God 135 | Object called the Joomla Factory (JFactory or 136 | \Joomla\CMS\Factory). It had a very opinionated approach on 137 | instantiating all sorts of globally used services, from the application 138 | itself, to the database, to the user objects, to the mailer object. If 139 | you wanted to write Unit Tests for your extension — or Joomla itself — 140 | it was the bane of your existence. In Joomla 4 we instead have a 141 | Container. It is not a real Dependency 143 | Injection Container as much as it is a Service 145 | Locator, meaning that it won't magically instantiate an object 146 | based on the type definitions in its class' constructor but it will let 147 | you retrieve the services you need to inject to your objects. Each 148 | extension — component, module, plugin and template — gets its own 149 | service locator and its own extension object which uses it. This makes 150 | it far easier to write unit tests for your code, especially your Models 151 | (which is where most of your business logic, therefore your code that 152 | needs testing, should already be). 153 | 154 | Web 155 | Asset Manager. In the past, whenever we wanted to load 156 | a JavaScript or CSS file we'd have to load its dependencies and finally 157 | our file. For example we might want to load jQuery, then load some 158 | Bootstrap core JavaScript files, then our JavaScript file. Each 159 | extension would do that and it lead to several chicken and egg problems. 160 | What if file A from extension X depends on files B and C and file B from 161 | extension Y depends on files C and D but D must be loaded before C? 162 | Bummer. The Web Asset Manager codifies the dependencies in a way which 163 | lets Joomla resolve them. It also lets you define alternative 164 | dependencies,e.g. a different JavaScript file to load depending on 165 | whether the user's browser supports JavaScript 167 | modules or not, and asset groups, e.g. a collection of CSS and 168 | JavaScript which are meant to be loaded together. This lets you split 169 | your CSS and JavaScript into smaller files which load in the correct 170 | order and improve the performance of your user's site. 171 | 172 | A new 173 | MVC. The MVC in Joomla 1.5 to 3.10 inclusive had 174 | changed very little. Previous attempts to modernise it failed 175 | ignominiously because they simultaneously failed to go far enough and 176 | maintain b/c (backwards compatibility). Joomla 4 has 177 | a new MVC model which is based on Dependency Injection and namespaces, 178 | it is more prescriptive, more flexible and more powerful than its 179 | predecessors. You can very easily extend a frontend model from a backend 180 | model instead of writing the same code twice or doing a contortionist 181 | act with PHP Traits. You can easily create custom HTML helpers without 182 | calling static functions, use categories without writing precarious 183 | database code, create object-oriented URL routers and much more which we 184 | will explore in this book. 185 | 186 | Hide-able inline help. Remember 187 | how Joomla 3 XML Forms looked like a word vomit with all the inline help 188 | text (field descriptions) being always visible? This was a bad interface 189 | for experienced users. At the same time, Joomla 4.0 removing all inline 190 | help text made the interface inapproachable for newcomers and end 191 | clients meant to use the site. With Joomla 4.1 it is now possible to 192 | have hide-able inline help text in your forms and your component 193 | configuration. The field descriptions are hidden by default and the user 194 | can show them by clicking on the Show Inline Help 195 | button in the interface. Now your extensions' interface can be 196 | simultaneously approachable for both new and experienced users. 197 | 198 | Prepared statements. SQL 199 | injection vulnerabilities have been almost de 200 | rigueur for any web software, Joomla extensions being no 201 | exception to that. Sure, Joomla does have some very nifty tools to get 202 | filtered input and escape it when placed inside database queries but not 203 | all input can be escaped sufficiently if you do not know its 204 | type (integer, string, array of one or the other). 205 | Moreover, despite best intentions, accidents can and do happen, e.g. 206 | forgetting to escape one piece of input you assumed it's an integer but 207 | it came through a path which never did check the input type nor did it 208 | try to typecast it to an integer! Joomla 4 introduced prepared 210 | statements which make these oversights and corner cases a thing 211 | of the past. You tell the query builder where you expect potentially 212 | user-originating data in your query, which data to use in there and what 213 | type this data is. You are guaranteed safe execution without worrying 214 | about SQL injection unless you try really hard to 215 | NOT let Joomla use a prepared statement. On the flip side, there are a 216 | few types of SQL queries which cannot execute in the context of prepared 217 | statements and required some code contortion to execute. 218 | 219 | Mail 220 | templates. In the past there were two ways to handle 221 | email for your extension. You could send plain text only email using 222 | language strings OR you would have to invent your own email template 223 | management. The former led to ugly email messages. The latter required 224 | reinventing a very complex device on each and every of your components. 225 | If you did not have a component, tough luck. Darn! Joomla 4's mail 226 | templates feature allows your users to use the Joomla WYSIWYG editor to 227 | create rich email templates with placeholders to be replaced by data 228 | provided by your extension. This feature looks half-finished in Joomla 4 229 | as it has no obvious way to register or update email templates. Don't 230 | worry, though, we do have a way to work around its shortcomings, 231 | complete with example code. 232 | 233 | Scheduled Tasks. Many extensions need to 235 | periodically execute some kind of code. For example, sending email 236 | newsletters, updating the prices of thousands of SKUs in an online shop 237 | from an Excel or XML file, running backups, you name it! In the past we 238 | had to reinvent the wheel on each extension we built. For example, we 239 | created ‘special’ URLs in our components or through com_ajax to be 240 | accessed with wget, cURL or a service like WebCRON.org periodically; or 241 | we created CLI scripts to be used with CRON jobs. We almost always 242 | offered more than one way to do things which led to a certain degree of 243 | code duplication. In all cases, the user was responsible for setting up 244 | CRON jobs or the equivalent on a third party service for every single 245 | task they needed to be executed periodically. This was a tall ask! 246 | Joomla 4.1 and later offers a new Scheduled Tasks feature which allows 247 | users to select which tasks they want to be executed, when to execute 248 | them and even configure their execution parameters — all within the 249 | familiar Joomla user interface. It even lets the task scheduler to be 250 | executed three ways: with a command line CRON job, a URL-based CRON job 251 | or automatically based on visitor traffic (lazy scheduling). The end 252 | user has to set up just the one CRON job or, if they are using lazy 253 | scheduling, just flip a switch. 254 | 255 | CLI 256 | Application. In the past we had to create bespoke CLI 257 | scripts for every task each of our extensions needed to allow to be 258 | executed from a command line context, be it a CRON job or a manually 259 | executed CLI helper tool. This required creating a new application and 260 | contend with the two facts that a) the base class changed at least twice 261 | in the last ten years and b) it lacked a lot of methods several core and 262 | third party classes were expecting to be present. This led to a lot of 263 | reinventing the wheel. The Joomla CLI Application is like a built-in 264 | version of WordPress' WP-CLI or Drupal's Drush in that it's based on the 265 | Symfony Console Components and can be easily extended using plugins 266 | which register command classes. Used wisely, it can enhance your 267 | extensions and help your advanced users who can use the CLI to automate 268 | things around their site. 269 | 270 | API 271 | Application. Joomla has historically been an HTML-only 272 | application. Yes, sure, you can have JSON, XML, Feed and Raw views but 273 | they feel bolted onto the HTML application; they are not a real API to 274 | your component. Joomla 4 introduced a brand-new application, the 275 | ApiApplication which lives in the api directory of 276 | your site. For now it's only accessible to Super Users but it provides a 277 | real RESTful JSON-based API to components which integrate with it. 278 | Integrating your component with the API application is as easy as 279 | creating a Web Services plugin and adding a few easy to create 280 | controllers and views in the API part of your component. That is to say, 281 | your component now has a backend, a frontend and an API side. You don't 282 | have to integrate with the API application but if 283 | you have something which could benefit from automation it is strongly 284 | encouraged to do so. 285 | 286 | Dashboards. Between Joomla 1.0 287 | and 3.10 inclusive Joomla only ever offered one dashboard, the main 288 | Control Panel page which loaded when you logged into your site's 289 | backend. In Joomla 1.0 to 1.6 it was hard-coded and inflexible. I added 290 | the ability to use plugins to render custom action buttons in Joomla 291 | 1.7, based on my experience with my software. Starting with Joomla 3.0 292 | you could now publish modules to add information 293 | panes to the Control Panel dashboard. If you wanted the same experience 294 | in your extension… tough luck. You would have to reinvent the wheel. 295 | Joomla 4.0 and later allow you to set up one or more dashboard 296 | pages for your own component which appear in the Joomla menu 297 | structure, under your component's menu item, and where you and your end 298 | users can publish any number of modules. 299 | 300 | Layouts everywhere. A lot of the 301 | HTML generated by Joomla, even throughout version 3, was statically 302 | coded in the PHP files implementing the business logic, making any kind 303 | of customisation impossible (or, at the very least, requiring a very 304 | judicious application of in-memory code editing, buffer stream wrappers 305 | and Reflection). Let's just say that if you disagreed with how a certain 306 | form field or HTML helper rendered its HTML you were out of luck. 307 | Layouts were introduced in Joomla 3.4 and later versions did make better 308 | use of them in various places but you still had to contend with several 309 | of the same issues. Not anymore! Joomla 4 uses layouts for every kind of 310 | HTML output. If you want to override how some core code renders in your 311 | component or your template you can easily do that by overriding the 312 | layout. Likewise, you are encouraged to use Layouts everywhere you have 313 | reusable HTML output in your extensions to make it easier for end users 314 | to override them in their template. 315 | 316 | Media options per component. 317 | Joomla 3.4 introduced an upload checker for all uploaded files based on 318 | the work I had done in Admin Tools. This was a massive leap in security 319 | as we codified the basic upload checks and encapsulated them in a way 320 | that made them run automatically whenever you were handling uploads. 321 | However, this was controlled by the Media component's 322 | (com_media) settings. This was great if your extension only 323 | ever needed static media files to be uploaded. If you wanted to allow 324 | your users to upload non-media files, or files otherwise not acceptable 325 | anywhere else com_media was exposed, such as ZIP, 7Z, and 326 | RAR files in a helpdesk component, you had to modify the Media options, 327 | allowing these files everywhere. The unfortunate 328 | solution to that was that third party component developers chose to 329 | disable the upload checks, undoing the security 330 | improvements we added in Joomla 3.4. This is no longer the case! Joomla 331 | 4 allows each component to have its own, private copy of Media settings 332 | for its own uploads. Any upload being handled by your component (not 333 | com_media!) will have these private settings applied. It's 334 | a bit of a chore BUT it lets you provide a much safer option for 335 | uploading files through your extension. 336 | 337 | There are many more improvements which I will not cover in this 338 | book. If you found out something cool and you'd like me to write a 339 | section for it, please do let me know. I can't promise it will 340 | definitely make it into the book but I will at least promise to give it 341 | a good thought and most likely a good try. 342 |
343 |
344 | --------------------------------------------------------------------------------