This document will try to walk you through writing, maintaining, and distribute extensions.
For instructions on obtaining and installing extension, see [[extensions/install]].
For instructions on using the framework's feature, see //another guide that isn't actually written yet//.
(NOTE) This document is correct for when it's written, but we plan to streamline most of the flow described here - see T15030, T15011, T15718, and related tasks.
== What are Extensions, really?
=== capabilities
=== Kinds of Extensions
- arc
- phorge application
- phorge not-app
== Creating an Extension
=== Requirements
For now, the best way to distribute extensions is by hosting it in a public Git repository. Users will use `git clone` to install it.
So, you'll need:
- A publicly-available Git hosting - it's available here (on request), and in many other places, such as GitHub.
- A Phorge Development Environment - that is, a computer with PHP, Arcanist, and [[https://we.phorge.it/book/phorge/article/installation_guide/ | Phorge installed]]. Preferably, not one that is used by anyone else. You'll need to [[https://we.phorge.it/book/contrib/article/developer_setup/ | configure it for development]]
- Some familiarity with writing code and using CLI tools.
=== Anatomy of an Extension
An Extension (sometimes called "a Libphutil library") is mostly made of PHP code, with some of our special glue.
Here's the file structure for a basic application extension:
```
.
├── LICENSE # Optional
├── README.md # Also Optional
└── src
├── mydemoapp # All code goes in here!
│ ├── application
│ │ └── MyDemoAppApplication.php
│ └── controller
│ └── MyDemoAppHomeController.php
├── __phutil_library_init__.php
├── __phutil_library_map__.php
└── .phutil_module_cache # <-- Make sure to add this file to .gitignore!
```
`LICENSE` and `README.md` are optional but recommended.
All your code will go under `src/mydemoapp/`; There's no requirements beyond that level, but we recommend dividing the files based on their role.
Here we have an Application class and a single Controller class. Note that their names include the extension name; Phorge class-loader doesn't support any sort of Namespace, so each class needs to have its extension name.
`__phutil_library_init__.php` is the file that makes this a "Libphutil library"; It contains a single instruction, `register_library()`, with the name of the library. This name has to be unique.
`__phutil_library_map__.php` is part of the class-loader capability; It includes a list of all classes in the extension.
Both these files are created and updated by running `arc liberate`. You'll need to re-run this every time you create a new PHP file or change the class hierarchy.
=== Getting started
To start writing your new extension:
1. `git init` a new directory for it. (Technically, you don't have to do this, but you really should)
2. `cd` into this directory, and create the `src` dir: `mkdir -p src`
4. Add `/src/.phutil_module_cache` to the `.gitignore` file.
3. run `arc liberate ./src/` to create an empty library. Arc will prompt you for a name - this has to be a unique name. Keep it lowercase and one word.
4. Assuming you're building a Phorge extension, add the path for your extension in Phorge's `conf/local/local.json` under `"load-libraries"`:
```name=conf/local/local.json, lang=json
"load-libraries": [
"/path/to/my-extension/src"
]
```
6. Load your Phorge install. You can navigate to `/config/` to see installed libraries under "Version Information".
6. Start adding PHP files. Run `arc liberate` after making changes, and browse to it in Phorge.
There's no "manifest" file for an extension - just the two `__phutil*.php` files that are loaded.
==== Writing Code
TODO: add details about how to write an Application and how to write an Arc extension. either here on separate page.
For now: https://we.phorge.it/book/contrib/article/phorge_code_layout/
==== Publishing Your Extension
When you're ready to publish your extension:
1. Make sure to run `arc liberate` and `celerity map` again, and to commit all your files.
2. `git push` to your selected hosting location.
3. Tell all your friends about it; Provide them with the public clone URI, and this link: [[extensions/install | How to Install An Extension]].
4. Add it to this page: [[community_resources]]
(NOTE) We plan to have a fancy Extension Store, but for now, the wiki page is the best we have.
=== linting and other fun stuff
// TODO : write this section //
you'll need to add `.arclint` and `.arcunit`, but also add the path of `phorge/src` to `load` in `.arcconfig`.
=== Resources: CSS, JavaScript and Images
//TODO: Write this section. This is more how-to-write-the-guide than actual guide.//
A Phorge extension can add new CSS and JS files; The [[ https://we.phorge.it/book/contrib/article/adding_new_css_and_js/ | basic guide here ]] describing the process for adding and using JS.
Here's an example extension that has CSS and JS files:
```
.
├──
├── rsrc
│ ├── css
│ │ └── comic-sans.css
│ └── js
│ └── behavior-my-tricks.js
└── src
├── mydemoapp
│ └── celerity
│ ├── MyDemoAppCelerityResources.php
│ └── map.php # This file is generated by `celerity map`
├── __phutil_library_init__.php
└── __phutil_library_map__.php
```
`MyDemoAppCelerityResources.php` will look something like this:
```lang=php, name=LightweightRTLCelerityResources.php
final class MyDemoAppCelerityResources extends CelerityResourcesOnDisk {
public function getName() {
return 'mydemoapp-resources';
}
public function getPathToResources() {
return phutil_get_library_root('mydemoapp').'/../rsrc');
}
public function getPathToMap() {
return phutil_get_library_root('mydemoapp').'/celerity/map.php');
}
}
```
(`mydemoapp` is the name of the extension library, as defined in `__phutil_library_init__.php`).
For updating the Celerity map in an extension:
1. Load the extension in Phorge (add it to `conf.local`)
2. Run `./bin/celerity map` from the //Phorge// directory.
This will update your celerity map in your directory.
//TODO: There's also tricks for regular images, and for sprite maps, but I'm not sure what they are.//