Changeset View
Changeset View
Standalone View
Standalone View
src/docs/contributor/adding_new_classes.diviner
Show All 15 Lines | |||||
============ | ============ | ||||
Phabricator primarily discovers functionality by looking at concrete subclasses | Phabricator primarily discovers functionality by looking at concrete subclasses | ||||
of some base class. For example, Phabricator determines which applications are | of some base class. For example, Phabricator determines which applications are | ||||
available by looking at all of the subclasses of | available by looking at all of the subclasses of | ||||
@{class@phabricator:PhabricatorApplication}. It | @{class@phabricator:PhabricatorApplication}. It | ||||
discovers available workflows in `arc` by looking at all of the subclasses of | discovers available workflows in `arc` by looking at all of the subclasses of | ||||
@{class@arcanist:ArcanistWorkflow}. It discovers available locales | @{class@arcanist:ArcanistWorkflow}. It discovers available locales | ||||
by looking at all of the subclasses of @{class@libphutil:PhutilLocale}. | by looking at all of the subclasses of @{class@arcanist:PhutilLocale}. | ||||
This pattern holds in many cases, so you can often add functionality by adding | This pattern holds in many cases, so you can often add functionality by adding | ||||
new classes with no other work. Phabricator will automatically discover and | new classes with no other work. Phabricator will automatically discover and | ||||
integrate the new capabilities or features at runtime. | integrate the new capabilities or features at runtime. | ||||
There are two main ways to add classes: | There are two main ways to add classes: | ||||
- **Extensions Directory**: This is a simple way to add new code. It is | - **Extensions Directory**: This is a simple way to add new code. It is | ||||
Show All 11 Lines | |||||
The easiest way to extend Phabricator by adding new classes is to drop them | The easiest way to extend Phabricator by adding new classes is to drop them | ||||
into the extensions directory, at `phabricator/src/extensions/`. | into the extensions directory, at `phabricator/src/extensions/`. | ||||
This is intended as a quick way to add small pieces of functionality, test new | This is intended as a quick way to add small pieces of functionality, test new | ||||
features, or get started on a larger project. Extending Phabricator like this | features, or get started on a larger project. Extending Phabricator like this | ||||
imposes a small performance penalty compared to using a library. | imposes a small performance penalty compared to using a library. | ||||
This directory exists in all libphutil libraries, so you can find similar | This directory exists in all libphutil libraries, so you can find a similar | ||||
directories in `arcanist/src/extensions/` and `libphutil/src/extensions/`. | directory in `arcanist/src/extensions/`. | ||||
For example, to add a new application, create a file like this one and add it | For example, to add a new application, create a file like this one and add it | ||||
to `phabricator/src/extensions/`. | to `phabricator/src/extensions/`. | ||||
```name=phabricator/src/extensions/ExampleApplication.php, lang=php | ```name=phabricator/src/extensions/ExampleApplication.php, lang=php | ||||
<?php | <?php | ||||
final class ExampleApplication extends PhabricatorApplication { | final class ExampleApplication extends PhabricatorApplication { | ||||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | |||||
For details on creating a `.arcconfig`, see | For details on creating a `.arcconfig`, see | ||||
@{article:Arcanist User Guide: Configuring a New Project}. In general, this | @{article:Arcanist User Guide: Configuring a New Project}. In general, this | ||||
tells `arc liberate` that it should look for symbols in Phabricator when | tells `arc liberate` that it should look for symbols in Phabricator when | ||||
performing static analysis. | performing static analysis. | ||||
NOTE: If Phabricator isn't located next to your custom library, specify a | NOTE: If Phabricator isn't located next to your custom library, specify a | ||||
path which actually points to the `phabricator/` directory. | path which actually points to the `phabricator/` directory. | ||||
You do not need to declare dependencies on `arcanist` or `libphutil`, | You do not need to declare dependencies on `arcanist`, since `arc liberate` | ||||
since `arc liberate` automatically loads them. | automatically loads them. | ||||
Finally, edit your Phabricator config to tell it to load your library at | Finally, edit your Phabricator config to tell it to load your library at | ||||
runtime, by adding it to `load-libraries`: | runtime, by adding it to `load-libraries`: | ||||
```lang=json | ```lang=json | ||||
... | ... | ||||
'load-libraries' => array( | 'load-libraries' => array( | ||||
'libcustom' => 'libcustom/src/', | 'libcustom' => 'libcustom/src/', | ||||
Show All 17 Lines | Now, run `arc liberate` to regenerate the static resource map: | ||||
libcustom/ $ arc liberate src/ | libcustom/ $ arc liberate src/ | ||||
This will automatically regenerate the static map of the library. | This will automatically regenerate the static map of the library. | ||||
What You Can Extend And Invoke | What You Can Extend And Invoke | ||||
============================== | ============================== | ||||
libphutil, Arcanist and Phabricator are strict about extensibility of classes | Arcanist and Phabricator are strict about extensibility of classes and | ||||
and visibility of methods and properties. Most classes are marked `final`, and | visibility of methods and properties. Most classes are marked `final`, and | ||||
methods have the minimum required visibility (protected or private). The goal | methods have the minimum required visibility (protected or private). The goal | ||||
of this strictness is to make it clear what you can safely extend, access, and | of this strictness is to make it clear what you can safely extend, access, and | ||||
invoke, so your code will keep working as the upstream changes. | invoke, so your code will keep working as the upstream changes. | ||||
IMPORTANT: We'll still break APIs frequently. The upstream does not support | IMPORTANT: We'll still break APIs frequently. The upstream does not support | ||||
extension development, and none of these APIs are stable. | extension development, and none of these APIs are stable. | ||||
When developing libraries to work with libphutil, Arcanist and Phabricator, you | When developing libraries to work with Arcanist and Phabricator, you should | ||||
should respect method and property visibility. | respect method and property visibility. | ||||
If you want to add features but can't figure out how to do it without changing | If you want to add features but can't figure out how to do it without changing | ||||
Phabricator code, here are some approaches you may be able to take: | Phabricator code, here are some approaches you may be able to take: | ||||
- {icon check, color=green} **Use Composition**: If possible, use composition | - {icon check, color=green} **Use Composition**: If possible, use composition | ||||
rather than extension to build your feature. | rather than extension to build your feature. | ||||
- {icon check, color=green} **Find Another Approach**: Check the | - {icon check, color=green} **Find Another Approach**: Check the | ||||
documentation for a better way to accomplish what you're trying to do. | documentation for a better way to accomplish what you're trying to do. | ||||
Show All 29 Lines |