diff --git a/src/docs/developer/phabricator_code_layout.diviner b/src/docs/developer/phabricator_code_layout.diviner new file mode 100644 index 0000000000..b737ace938 --- /dev/null +++ b/src/docs/developer/phabricator_code_layout.diviner @@ -0,0 +1,128 @@ +@title Phabricator Code Layout +@group developer + +Guide to Phabricator code layout, including how URI mapping works through +application class and subdirectory organization best practices. + += URI Mapping = + +When a user visits a Phabricator URI, the Phabricator infrastructure parses +that URI with a regular expression to determine what controller class to load. +For now, that regular expression is hard-coded inside the +@{class:AphrontDefaultApplicationConfiguration} within the ##getURIMap## +method. Use the existing entries as examples for adding your own entries. + +The Phabricator infrastructure knows where a given controller class lives on +disk from a cache file the Arcanist phutil mapper generates. This mapping +should be updated whenever new classes or files are added: + + /path/to/arcanist/scripts/phutil_mapper.php /path/to/phabricator/src + +Finally, a given controller class will map to an application which will have +most of its code in standardized subdirectories and classes. + += Best Practice Class and Subdirectory Organization = + +Suppose you were working on the application ##Derp##. + + phabricator/src/applications/derp/ + +If ##Derp## were as simple as possible, it would have one subdirectory: + + phabricator/src/applications/derp/controller/ + +containing the file ##DerpController.php## with the class + + - ##DerpController##: minimally implements a ##processRequest()## method + which returns some @{class:AphrontResponse} object. The class would probably + extend @{class:PhabricatorController}. + +plus an auto-generated ##__init__.php## file. + +NOTE: ##__init.php__## files are generated and maintained via `arc lint`. + +If ##Derp## were (relatively) complex, one could reasonably expect to see +the following directory layout: + + phabricator/src/applications/derp/constants/ + phabricator/src/applications/derp/controller/ + phabricator/src/applications/derp/editor/ + phabricator/src/applications/derp/exception/ + phabricator/src/applications/derp/query/ + phabricator/src/applications/derp/replyhandler/ + phabricator/src/applications/derp/storage/ + phabricator/src/applications/derp/view/ + phabricator/src/applications/conduit/method/derp/ + +(The following two folders are also likely to be included for javascript and +css respectively. However, static resources are largely outside the scope of +this document. See @{article:Adding New CSS and JS}.) + + phabricator/webroot/rsc/js/application/derp/ + phabricator/webroot/rsc/css/application/derp/ + +These directories under ##phabricator/src/applications/derp/## represent +the basic set of class types from which most Phabrictor applications are +assembled. Each would contain a class file and an ##__init__.php## file. +For ##Derp##, these classes could be something like: + + - **DerpConstants**: constants used in the ##Derp## application. + - **DerpController**: business logic providing functionality for a given + URI. Typically, controllers load data via Storage or Query classes, then + present the data to the user via one or more View classes. + - **DerpEditor**: business logic for workflows that change one or more + Storage objects. Editor classes are only necessary for particularly + complicated edits and should be used pragmatically verus Storage objects. + - **DerpException**: exceptions used in the ##Derp## application. + - **DerpQuery**: query one or more storage objects for pertinent ##Derp## + application data. @{class:PhabricatorOffsetPagedQuery} is particularly + handy for pagination and works well with @{class:AphrontPagerView}. + - **DerpReplyHandler**: business logic from any configured email interactions + users can have with the ##Derp## application. + - **DerpStorage**: storage objects for the ##Derp## application. Typically + there is a base class which extends @{class:PhabricatorLiskDAO} to configure + application-wide storage settings like the application (thus database) name. + Reading more about the @{class:LiskDAO} is highly recommended. + - **DerpView**: view objects for the ##Derp## application. Typically these + extend @{class:AphrontView}. + - **ConduitAPI_derp_Method**: provides any and all ##Derp## application + functionality that is accessible over Conduit. + +However, it is likely that ##Derp## is even more complex, and rather than +containing a class and an ##__init__.php## file, each directory has +subdirectories of its own. A typical example happens around the CRUD of an +object: + + phbaricator/src/application/derp/controller/base/ + phabricator/src/application/derp/controller/delete/ + phabricator/src/application/derp/controller/edit/ + phabricator/src/application/derp/controller/list/ + phabricator/src/application/derp/controller/view/ + +Which would then each contain a class and an ##__init__.php## file mapping to +corresponding classes + + - **DerpBaseController**: typically extends @{class:PhabricatorController}, + implements ##buildStandardPageResponse## with the ##Derp## application name + and other ##Derp##-specific meta-data, and contains any controller-specific + functionality used throughout the ##Derp## application. + - **DerpDeleteController**: typically extends ##DerpBaseController## and + presents a confirmation dialogue to the user about deleting a ##Derp##. + - **DerpEditController**: typically extends ##DerpBaseController## and + presents a form to create and edit ##Derps##. Most likely uses + @{class:AphrontFormView} and various ##AphrontFormXControl## classes such as + @{class:AphrontFormTextControl} to create the form. + - **DerpListController**: typically extends ##DerpBaseController## and displays + a set of one or more ##Derps##. Might use @{class:AphrontTableView} to create + a table of ##Derps##. + - **DerpViewController**: typically extends ##DerpBaseController## and displays + a single ##Derp##. + +NOTE: each directory will have a class file with an ##__init__.php## or +subdirectories; never both. + += Next Steps = + + - Learn about @{article:Adding New CSS and JS}; or + - learn about the @{class:LiskDAO}; or + - learn how to contribute (see @{article:Contributor Introduction}).