[Rt-commit] rt branch, 4.0/writing-rt-extensions-doc, repushed

Jim Brandt jbrandt at bestpractical.com
Thu Jan 16 11:01:44 EST 2014


The branch 4.0/writing-rt-extensions-doc was deleted and repushed:
       was 09d9455fb36279a0135e87815d9414e17a3c5331
       now 5e45b9ab80dd658273621d20e5e62a835ae56b31

1:  1b9e5a2 ! 1:  5e45b9a New doc for writing RT extensions
    @@ -1,6 +1,6 @@
     Author: Jim Brandt <jbrandt at bestpractical.com>
     
    -    New doc for writing extensions
    +    New doc for writing RT extensions
     
     diff --git a/docs/writing-extensions.pod b/docs/writing-extensions.pod
     new file mode 100644
    @@ -43,9 +43,9 @@
     +=back
     +
     +If this is your first time using L<Dist::Zilla>, you can set up your
    -+CPAN detals by running:
    -+
    -+    # dzil setup
    ++CPAN details by running:
    ++
    ++    dzil setup
     +
     +You can read about L<Dist::Zilla> and the C<dzil> command at L<http://dzil.org>.
     +
    @@ -53,7 +53,7 @@
     +extension and run the following, replacing Demo with a descriptive name
     +for your new extension:
     +
    -+    # dzil new -P RTx RT-Extension-Demo
    ++    dzil new -P RTx RT-Extension-Demo
     +
     +You'll see something like:
     +
    @@ -62,11 +62,11 @@
     +    [DZ] dist minted in ./RT-Extension-Demo
     +
     +If you're stuck on a name, take a look at some of the existing RT extensions.
    -+You can also ask around the office or on IRC to see what people thinks
    ++You can also ask around IRC (#rt on irc.perl.org) to see what people think
     +makes sense for what the extension will do.
     +
     +You'll now have a directory with the basic files for your extension.
    -+Included is a gitignore file which is handy if you use git for your version
    ++Included is a F<gitignore> file, which is handy if you use git for your version
     +control like we do. If you don't use git, feel free to delete it, but we hope
     +you're using some sort of version control for your work.
     +
    @@ -74,7 +74,8 @@
     +
     +There are several places to put code to provide your new features
     +and if you follow the guidelines below, you'll make sure things
    -+get installed in the right places when you're ready to use it.
    ++get installed in the right places when you're ready to use it. These standards
    ++apply to RT 4.0 and 4.2 and any differences between the two are noted below.
     +
     +=head2 Module Code
     +
    @@ -93,43 +94,108 @@
     +Your Mason templates should go in an C<html> directory with the appropriate
     +directory structure to make sure the callbacks are executed.
     +
    ++If you are creating completely new pages for RT, you can put these under the
    ++C<html> directory also. You can create subdirectories as needed to add the
    ++page to existing RT paths (like Tools) or to create new directories for your
    ++extension.
    ++
    ++=head2 CSS and Javascript
    ++
    ++Where these files live differs between RT 4.2 and above, and RT 4.0 and
    ++below; if you need your extension to be compatible with both, you may
    ++need to provide both configurations.  On RT 4.2 and above, create a
    ++C<static> directory at the top level under your extension, and under
    ++that a C<css> directory and a C<js> directory. Before RT 4.2, you should
    ++create C<css> and C<js> directories in C<html/NoAuth/>.
    ++
    ++To add files to RT's include paths, you can use the L<RT/AddStyleSheets> and
    ++L<RT/AddJavascript> methods available in the L<RT> module. You can put the
    ++lines near the top of your module code (in your "Demo.pm" file). If you set up
    ++the paths correctly, you should only need to set the file names like this:
    ++
    ++    RT->AddStyleSheets('myextension.css');
    ++    RT->AddJavaScript('myextension.js');
    ++
     +=head2 Creating Objects in RT
     +
     +If you need to have users create a group, scrip, template, or some other
    -+object in their RT instance, you can automate this using an C<initialdata>
    -+file. If you need this, the file should go in the C<etc> directory.
    -+See also L<docs/initialdata>.
    ++object in their RT instance, you can automate this using an F<initialdata>
    ++file. If you need this, the file should go in the C<etc> directory. This will
    ++allow users to easily run the F<initialdata> file when installing with:
    ++
    ++    make initdb
     +
     +=head2 Module::Install Files
     +
     +As mentioned above, the RT extension tools are set up to use L<Module::Install>
     +to manage the distribution. When you run
     +
    -+    # perl Makefile.PL
    ++    perl Makefile.PL
     +
     +for the first time, L<Module::Install> will create an C<inc> directory for all
    -+of the files it needs. Since you are the author, you should create a
    -+C<.author> directory (note the . in the directory name) in the C<inc>
    ++of the files it needs. Since you are the author, a C<.author> directory
    ++(note the . in the directory name) is created for you in the C<inc>
     +directory. When L<Module::Install> detects this directory, it does things only
     +the author needs, like pulling in modules to put in the C<inc> directory.
    -+Once you have this set up, L<Module::Install> should mostly do the right thing,
    -+but you can read more about it in the module documentation.
    ++Once you have this set up, L<Module::Install> should mostly do the right thing.
    ++You can find details in the module documentation.
     +
     +=head2 Tests
    ++
    ++=head3 Test Directory
     +
     +You can create tests for your new extension just as with other perl code
     +you write. However, unlike typical CPAN modules where users run the tests
     +as a step in the installation process, RT users installing extensions don't
     +usually run tests. This is because running the tests requires your RT to
     +be set up in development mode which involves installing some additional
    -+modules and having a dev instance. To prevent users from accidentally
    -+running the tests, we put them in a C<xt> directory rather than the typical
    -+C<t> directory.
    ++modules and having a test database. To prevent users from accidentally
    ++running the tests, which will fail without this testing setup, we put them in
    ++a C<xt> directory rather than the typical C<t> directory.
    ++
    ++=head3 Writing Extension Tests
    ++
    ++If you want to write and run tests yourself, you'll need a development RT
    ++instance set up. Since you are building an extension, you probably already have
    ++one. To start with testing, set the C<RTHOME> environment variable to the base
    ++directory of your RT instance so your extension tests run against the right
    ++instance. This is especially useful if you have your test RT installed in a non-standard location.
    ++
    ++Next, you need to subclass from L<RT::Test>
    ++which gives you access to the test RT and a test database for running
    ++tests. For this, you'll create a F<Test.pm> file in your C<lib> tree.
    ++The easiest way to set up the test module to pull in F<RT::Test> is to look at
    ++an example extension. L<RT::Extension::RepeatTicket>, for example, has a
    ++testing configuration you can borrow from.
    ++
    ++You'll notice that the file included in the extension is
    ++F<lib/RT/Extension/RepeatTicket/Test.pm.in>. This is because there are paths
    ++that are set based on your RT location, so the actual F<Test.pm> file is
    ++written when you run F<Makefile.PL> with appropriate paths substituted
    ++when F<Makefile.PL> is run. L<Module::Install> provides an interface to make
    ++this easy with a C<substitute> feature. The substitution code is in the
    ++F<Makefile.PL> file and you can borrow that as well.
    ++
    ++Once you have that set up, add this to the top of your test files:
    ++
    ++    use RT::Extension::Demo::Test tests => undef;
    ++
    ++and you'll be able to run tests in the context of a fully functioning RT
    ++instance. The L<RT::Test>
    ++documentation describes some of the helper methods available and you can
    ++look at other extensions and the RT source code for examples of how to
    ++do things like create tickets, queues, and users, how to set rights, and
    ++how to modify tickets to simulate various RT tasks.
    ++
    ++If you have a command-line component in your extension, the easiest way
    ++to test it is to set up a C<run> method using the Modulino approach.
    ++You can find an example of this approach in L<RT::Extension::RepeatTicket>
    ++in the F<bin> directory.
     +
     +=head2 Patches
     +
     +If you need to provide patches to RT for any reason, you can put them in
    -+a C<patches> directory. See L<'Changes to RT'> for more information.
    ++a C<patches> directory. See L</"Changes to RT"> for more information.
     +
     +=head1 Callbacks
     +
    @@ -140,21 +206,23 @@
     +
     +=head2 Directory Structure
     +
    -+RT looks in the following path for callbacks:
    -+
    -+    rt_base/local/html/Callbacks/[custom_name]/[rt mason path]/[callback name]
    ++RT looks in the F<local/plugins> directory under the RT base directory for
    ++extensions registered with the C<@Plugins> configuration. RT then uses the
    ++following structure when looking for callbacks:
    ++
    ++    local/plugins/[ext name]/html/Callbacks/[custom name]/[rt mason path]/[callback name]
     +
     +The extension installation process will handle some of this for you by putting
    -+your html directory under C<local> as part of the installation process.
    -+You need to make sure the path under C<html> is correct since that is installed
    -+as-is.
    ++your html directory under F<local/plugins/[ext name]> as part of the
    ++installation process. You need to make sure the path under C<html> is correct
    ++since that is installed as-is.
     +
     +The C<Callbacks> directory is required. The next directory can be named
     +anything and is provided to allow RT owners to keep local files organized
     +in a way that makes sense to them. In the case of
     +an extension, you should name the directory the same as your extension.
     +So if your extension is C<RT::Extension::Demo>, you should create a
    -+C<RT-Extension-Demo> directory under C<Callbacks>.
    ++F<RT-Extension-Demo> directory under F<Callbacks>.
     +
     +The rest of the path is determined by the RT Mason code and the callback you
     +want to use. You can find callbacks by looking for calls to the C<callback>
    @@ -165,25 +233,25 @@
     +
     +As an example, assume you wanted to modify the ticket update page to put
     +something after the Time Worked field. You run the above and see there is
    -+a callback in C<share/html/Ticket/Update.html> that looks like this:
    ++a callback in F<share/html/Ticket/Update.html> that looks like this:
     +
     +    $m->callback( %ARGS, CallbackName => 'AfterWorked', Ticket => $TicketObj );
     +
    -+You look at the Update.html file and see that the callback is located
    ++You look at the F<Update.html> file and see that the callback is located
     +right after the Time Worked field. To add some code that RT will
     +run at that point, you would create the directory:
     +
     +    html/Callbacks/RT-Extension-Demo/Ticket/Update.html/
     +
    -+Note that Update.html is a file in the RT source, but it becomes a directory
    ++Note that F<Update.html> is a file in the RT source, but it becomes a directory
     +in your extension code. You then create a file with the name of the
    -+callback, in this case C<AfterWorked>, and that's where you put your code.
    ++callback, in this case F<AfterWorked>, and that's where you put your code.
     +So the full path and file would be:
     +
     +    html/Callbacks/RT-Extension-Demo/Ticket/Update.html/AfterWorked
     +
     +If you see a callback that doesn't have a C<CallbackName> parameter, name
    -+your file C<Default> and it will get invoked since that is the default
    ++your file F<Default> and it will get invoked since that is the default
     +callback name when one isn't provided.
     +
     +=head2 Callback Parameters
    @@ -210,6 +278,47 @@
     +to give you idea what you can do in your callback code. You can also look
     +at other extensions for examples of how people use callbacks to modify
     +and extend RT.
    ++
    ++=head1 Adding and Modifying Menus
    ++
    ++You can modify all of RT's menus using callbacks as described in L</Callbacks>.
    ++The file in RT that controls menus is:
    ++
    ++    share/html/Elements/Tabs
    ++
    ++and you'll find a Privileged and SelfService callback which gives you access
    ++to those two sets of menus. In those callbacks, you can add to or change
    ++the main menu, the page menu, or the page widgets.
    ++
    ++You can look at the F<Tabs> file itself for examples of adding menu items.
    ++The menu object is a L<RT::Interface::Web::Menu> and you can find details on
    ++the available parameters in the documentation.
    ++
    ++Here are some simple examples of what you might do in a callback:
    ++
    ++    <%init>
    ++    # Add a brand new root menu item
    ++    my $bps = Menu()->child(
    ++        'bps', # any unique identifier
    ++        title => 'Corporate',
    ++        path  => 'http://bestpractical.com'
    ++    );
    ++
    ++    #Add a submenu item to this root menu item
    ++    $bps->child(
    ++        'wiki',
    ++        title => 'Wiki',
    ++        path  => 'http://wiki.bestpractical.com',
    ++    );
    ++
    ++    #Retrieve the 'actions' page menu item
    ++    if (my $actions = PageMenu->child('actions')) {
    ++        $actions->child(
    ++            'newitem',
    ++            title => loc('New Action'), path => '/new/thing/here',
    ++        )
    ++    }
    ++    </%init>
     +
     +=head1 Changes to RT
     +
    @@ -227,10 +336,10 @@
     +if you know they will eventually be merged into RT. Otherwise, you
     +may have to provide versions of your patches for each release of RT.
     +You can read more about getting changes accepted into RT in the
    -+L<docs/hacking> document.
    ++L<hacking> document. We generally accept patches that add new callbacks.
     +
     +Create a C<patches> directory in your extension distribution to hold
    -+your patch files. Name the patch files with the latest verison of RT
    ++your patch files. Name the patch files with the latest version of RT
     +that needs the patch. For example, if the patch is needed for RT 4.0.7,
     +name your patch C<4.0.7-some-patch.diff>. That tells users that if they
     +are using RT 4.0.7 or earlier, they need to apply the patch. If your
    @@ -240,19 +349,37 @@
     +Also remember to update your install documentation to remind users to apply
     +the patch.
     +
    ++=head1 Preparing for CPAN
    ++
    ++When you have your extension ready and want to release it to the world, you
    ++can do so with a few simple steps.
    ++
    ++Assuming you have run C<perl Makefile.PL> and you created the F<inc/.author>
    ++directory as described above, a F<README> file will be created for you. You can
    ++now type:
    ++
    ++    make manifest
    ++
    ++and a F<MANIFEST> file will be created. It should contain all of the needed
    ++to install and run your extension. If you followed the steps above, you'll have
    ++also have a F<inc> directory which contains L<Module::Install> code. Note that
    ++this code should also be included with your extension when you release it as
    ++it's part of the install process.
    ++
    ++Next, check to see if everything is ready with:
    ++
    ++    make distcheck
    ++
    ++If anything is missing, it will be reported and you can go fix it.
    ++When the check is clean, run:
    ++
    ++    make dist
    ++
    ++and a new distribution will be created in the form of a tarred and gzipped
    ++file.
    ++
    ++Now you can upload to cpan with the F<cpan-upload> utility provided by
    ++L<CPAN::Uploader> or your favorite method of uploading to CPAN.
    ++
     +=cut
     +
    -+# TODO:
    -+
    -+# Add docs about how to set up testing
    -+
    -+# Add docs about final distribution steps (make dist, etc.)
    -+
    -+# Make sure link to initialdata.pod works
    -+
    -+# Add docs about best way to extend email handling with
    -+# mail plugins
    -+
    -+# Add info on creating additional web pages in html, where
    -+# they are installed, and how to add to the RT menu
    -
2:  e7d1df9 < -:  ------- Fix internal pod link
3:  76b0cde < -:  ------- Update .author directory details
4:  e6c5c35 < -:  ------- Add details on setting up the static directory.
5:  38f4250 < -:  ------- Minor nits
6:  72d37ff < -:  ------- Add docs on writing tests and clean up callback path example
7:  abafcef < -:  ------- Add docs on final CPAN release steps
8:  f3565c2 < -:  ------- Add menu example plus some link cleanup
9:  09d9455 < -:  ------- Spellcheck



More information about the rt-commit mailing list