├── .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 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/pandoc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/phing.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $USER_HOME$/.composer/vendor/bin/phing
5 |
6 |
--------------------------------------------------------------------------------
/.idea/php.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
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 |
--------------------------------------------------------------------------------