[tools 2/2] testbot/cgi: Document the CGI classes.

Francois Gouget fgouget at codeweavers.com
Thu Mar 24 10:37:53 CDT 2022


Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
Again no impact on the website since only the POD documentation changes. 
With this groundwork in place the framework improvements will then 
resume.
---
 .../lib/ObjectModel/CGI/CollectionBlock.pm    |  87 +++++++++-
 .../ObjectModel/CGI/CollectionBlockForPage.pm |   4 +
 testbot/lib/ObjectModel/CGI/CollectionPage.pm |   8 +
 testbot/lib/ObjectModel/CGI/FormPage.pm       | 158 +++++++++++++++++-
 testbot/lib/ObjectModel/CGI/ItemPage.pm       |   4 +-
 testbot/lib/ObjectModel/CGI/Page.pm           |  68 +++++++-
 testbot/lib/WineTestBot/CGI/PageBase.pm       |  40 ++++-
 7 files changed, 359 insertions(+), 10 deletions(-)

diff --git a/testbot/lib/ObjectModel/CGI/CollectionBlock.pm b/testbot/lib/ObjectModel/CGI/CollectionBlock.pm
index 13bbc4c3f..6f5c4d5fa 100644
--- a/testbot/lib/ObjectModel/CGI/CollectionBlock.pm
+++ b/testbot/lib/ObjectModel/CGI/CollectionBlock.pm
@@ -2,6 +2,7 @@
 # Base class for list blocks
 #
 # Copyright 2009 Ge van Geldorp
+# Copyright 2014, 2018, 2021-2022 Francois Gouget
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -23,6 +24,45 @@ use strict;
 
 ObjectModel::CGI::CollectionBlock - Base class for list blocks
 
+Generates a table representing the items contained in the specified collection
+and provides support for:
+- Linking to a page providing a detailed view of a given item.
+- Selecting individual items and performing an action on them.
+  See GetItemActions() and OnItemActions().
+- Performing a global action. See GetActions() and OnAction().
+
+Note that a web page may contain multiple collection blocks.
+
+Also, because this is only one part of a web page, some methods, such as those
+dealing with errors, are delegated to the EnclosingPage object which must
+implement the ObjectModel::CGI::Page interface.
+
+Other methods are designed so they can be overriden by the enclosing page as
+a way to allow it to modify how the collection block looks or behaves. These
+methods can be identified by their CallXxx() trampoline. The override
+mechanism works as follows:
+- The CollectionBlock class and any subclass should never call overridable
+  methods directly. Instead they should call the corresponding CallXxx()
+  trampoline.
+- The CollectionBlock class provides a default CallXxx() implementation which
+  simply calls the corresponding Xxx() method. This allows using the
+  CollectionBlock as is.
+- Pages that want to customize the CollectionBlock behavior should use the
+  CollectionBlockForPage class instead. That class provides an alternative
+  implementation for each CallXxx(...) method that calls
+  $self->{EnclosingPage}->Xxx($CollectionBlock, ...). Note how the Xxx()
+  method in the enclosing page gets an extra parameter so it can both know
+  which collection block it received the call from, and call the collection
+  block methods.
+- The page should in turn provide implementations for all the Xxx() methods.
+  The simplest way to do so is for such pages use CollectionPage as their base
+  class. CollectionPage provides default Xxx($CollectionBlock,...)
+  implementations that just reflect these calls back to
+  $CollectionBlock->Xxx().
+
+Of course an alternative way for a page to customize the collection block
+behavior is to subclass it and use that subclass instead.
+
 =cut
 
 package ObjectModel::CGI::CollectionBlock;
@@ -103,6 +143,19 @@ sub CallDisplayProperty($$)
   return $self->DisplayProperty($PropertyDescriptor);
 }
 
+=pod
+=over 12
+
+=item C<DisplayProperty()>
+
+Specifies whether to hide the given property.
+
+Any value evaluating to false specifies that the property should be hidden and
+all others that it should be shown.
+
+=back
+=cut
+
 sub DisplayProperty($$)
 {
   my ($self, $PropertyDescriptor) = @_;
@@ -142,6 +195,7 @@ sub GetDisplayValue($$$)
   {
     if (defined($Value))
     {
+      # Note: This only supports single-key Itemrefs
       foreach $PropertyDescriptor (@{$Value->GetPropertyDescriptors()})
       {
         if ($PropertyDescriptor->GetIsKey())
@@ -517,9 +571,12 @@ sub CallGetItemActions($)
 
 Returns the list of per-item actions.
 
-This is a set of actions that is applied to each selected item in the
+This is a set of actions that can be applied to each selected item in the
 collection.
 
+If the set is empty the GUI will provide no way to select items. Otherwise a
+column of checkboxes is added.
+
 =back
 =cut
 
@@ -536,6 +593,19 @@ sub CallOnItemAction($$$)
   return $self->OnItemAction($Item, $Action);
 }
 
+=pod
+=over 12
+
+=item C<OnItemAction()>
+
+This method is called to apply $Action to each selected item.
+
+Note that it is the responsibility of this method to validate the property
+values by calling Validate() before performing the action.
+
+=back
+=cut
+
 sub OnItemAction($$$)
 {
   my ($self, $Item, $Action) = @_;
@@ -588,6 +658,21 @@ sub GetActions($)
   return \@Actions;
 }
 
+=pod
+=over 12
+
+=item C<OnAction()>
+
+Implements the "Add" and per-item actions.
+
+Note that it is the responsibility of this method to validate the property
+values by calling Validate() before performing the action.
+
+=back
+=cut
+
+# Note that there is no call to OnAction() in the CollectionBlock class so
+# there is no need for a CallOnAction() trampoline.
 sub OnAction($$)
 {
   my ($self, $Action) = @_;
diff --git a/testbot/lib/ObjectModel/CGI/CollectionBlockForPage.pm b/testbot/lib/ObjectModel/CGI/CollectionBlockForPage.pm
index 94d5f8672..5bdc7d32e 100644
--- a/testbot/lib/ObjectModel/CGI/CollectionBlockForPage.pm
+++ b/testbot/lib/ObjectModel/CGI/CollectionBlockForPage.pm
@@ -2,6 +2,7 @@
 # Collection block for list pages
 #
 # Copyright 2009 Ge van Geldorp
+# Copyright 2014, 2017-2018, 2022 Francois Gouget
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -25,6 +26,9 @@ package ObjectModel::CGI::CollectionBlockForPage;
 
 ObjectModel::CGI::CollectionBlockForPage - Collection block for list pages
 
+Allows the CollectionPage class to provide implementations for most of the
+CollectionBlock methods. See CollectionBlock for details.
+
 =cut
 
 use ObjectModel::CGI::CollectionBlock;
diff --git a/testbot/lib/ObjectModel/CGI/CollectionPage.pm b/testbot/lib/ObjectModel/CGI/CollectionPage.pm
index 993f18685..d59310be5 100644
--- a/testbot/lib/ObjectModel/CGI/CollectionPage.pm
+++ b/testbot/lib/ObjectModel/CGI/CollectionPage.pm
@@ -2,6 +2,7 @@
 # Base class for list pages
 #
 # Copyright 2009 Ge van Geldorp
+# Copyright 2014, 2017-2018, 2022 Francois Gouget
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -25,6 +26,13 @@ package ObjectModel::CGI::CollectionPage;
 
 ObjectModel::CGI::CollectionPage - Base class for list pages
 
+Generates a page containing a single collection block.
+
+It uses the CollectionBlockForPage class which means CollectionPage implements
+both the ObjectModel::CGI::Page and ObjectModel::CGI::CollectionBlock
+interfaces. The latter allows it to customize the collection block without
+having to define a CollectionBlock subclass.
+
 =cut
 
 use ObjectModel::CGI::Page;
diff --git a/testbot/lib/ObjectModel/CGI/FormPage.pm b/testbot/lib/ObjectModel/CGI/FormPage.pm
index 588ea55b7..9e34a736d 100644
--- a/testbot/lib/ObjectModel/CGI/FormPage.pm
+++ b/testbot/lib/ObjectModel/CGI/FormPage.pm
@@ -2,7 +2,7 @@
 # Base class for web pages containing a form
 #
 # Copyright 2009 Ge van Geldorp
-# Copyright 2012 Francois Gouget
+# Copyright 2012, 2014, 2017-2018, 2022 Francois Gouget
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -26,12 +26,55 @@ package ObjectModel::CGI::FormPage;
 
 ObjectModel::CGI::FormPage - Base class for web forms
 
+This class generates a page that:
+- Displays a list of properties, allows editing them, or a mix of both.
+- Provides a list of actions that can be applied after visualizing or editing
+  the properties.
+- Provides the framework for validating the property values and saving them.
+
+This page has the following properties:
+=over
+
+=item Method
+Specifies how to send the CGI parameters for the property values (get or post).
+
+=item HasRequired
+True if the form has fields that are mandatory.
+
+=item ActionPerformed
+True if an action was specified and performed.
+
+=back
+
+A typical use takes this form:
+
+my $PropertyDescriptors = [ ... ];
+my $MyFormPage = MyFormPage->new($Request, "required-privileges", $PropertyDescriptors);
+$MyFormPage->GeneratePage();
+
 =cut
 
 use ObjectModel::CGI::Page;
 our @ISA = qw(ObjectModel::CGI::Page);
 
 
+=pod
+=over 12
+
+=item C<_initialize()>
+
+This method is called by the constructor to initialize the form page.
+
+The PropertyDescriptors parameter specifies a reference to the list of
+properties that the form should show or allow editing, as specified by
+DisplayProperty(). It may be undefined if determining the property list is
+delegated to GetPropertyDescriptors().
+
+See also Page::new().
+
+=back
+=cut
+
 sub _initialize($$$$)
 {
   my ($self, $Request, $RequiredRole, $PropertyDescriptors) = @_;
@@ -49,6 +92,20 @@ sub _initialize($$$$)
 # Property handling
 #
 
+=pod
+=over 12
+
+=item C<GetPropertyDescriptors()>
+
+Returns a reference to a list of ObjectModel::PropertyDescriptor objects
+describing the fields to be displayed / edited. This also defines the set of
+CGI parameters that the page supports.
+
+This must not return undef.
+
+=back
+=cut
+
 sub GetPropertyDescriptors($)
 {
   my ($self) = @_;
@@ -72,6 +129,32 @@ sub GetPropertyDescriptorByName($$)
   return undef;
 }
 
+=pod
+=over 12
+
+=item C<DisplayProperty()>
+
+Specifies whether to hide, display or allow editing the given property.
+
+Return values:
+=over
+=item ""
+Any value evaluating to false specifies that the property should be hidden.
+
+=item "ro"
+Specifies that the property is read-only, i.e. GenerateField() should display
+it instead of generating an edit field.
+
+=item "rw"
+Specifies that GenerateField() should allow editing the property.
+Note that this implies that $PropertyDescriptor->GetName() should be a valid
+HTTP parameter name.
+
+=back
+
+=back
+=cut
+
 sub DisplayProperty($$)
 {
   my ($self, $PropertyDescriptor) = @_;
@@ -92,6 +175,20 @@ sub DisplayProperty($$)
          "ro";
 }
 
+=pod
+=over 12
+
+=item C<GetPropertyValue()>
+
+Returns the underlying property value.
+
+This is used to initialize the form with the properties of the 'object' to be
+modified or displayed. The default implementation considers that there is no
+underlying value.
+
+=back
+=cut
+
 sub GetPropertyValue($$)
 {
   #my ($self, $PropertyDescriptor) = @_;
@@ -135,6 +232,17 @@ sub GetInputType($$)
          "text";
 }
 
+=pod
+=over 12
+
+=item C<GenerateRequired()>
+
+Generates an HTML snippet to be put next to an input field to indicate it must
+be set.
+
+=back
+=cut
+
 sub GenerateRequired($$)
 {
   my ($self, $PropertyDescriptor) = @_;
@@ -356,6 +464,26 @@ sub GeneratePage($)
 # Validating and saving the form content
 #
 
+=pod
+=over 12
+
+=item C<Validate()>
+
+Validates the property values.
+
+Note that this method is not called in the default implementation. Subclasses
+would likely want to call it in OnAction() or possibly in _initialize() after
+having set up the property descriptors list.
+
+The default implementation only checks the individual property values using
+the corresponding property descriptor's ValidateValue() method.
+
+Any cross-property consistency checks should be done by redefining this method
+in subclasses.
+
+=back
+=cut
+
 sub Validate($)
 {
   my ($self) = @_;
@@ -419,6 +547,20 @@ sub Save($)
 # Actions handling
 #
 
+=pod
+=over 12
+
+=item C<GetActions()>
+
+Returns a list of actions that can be applied after completing or reading this
+form. Each action is a string which is used as the label of a button at the
+bottom of the form.
+
+By default there is no action.
+
+=back
+=cut
+
 sub GetActions($)
 {
   #my ($self) = @_;
@@ -437,6 +579,20 @@ sub GenerateActions($)
   print "</div>\n";
 }
 
+=pod
+=over 12
+
+=item C<OnAction()>
+
+This method should be redefined in subclasses to implement the supported
+actions.
+
+Note that it is the responsibility of this method to validate the property
+values by calling Validate() before performing the action.
+
+=back
+=cut
+
 sub OnAction($$)
 {
   my ($self, $Action) = @_;
diff --git a/testbot/lib/ObjectModel/CGI/ItemPage.pm b/testbot/lib/ObjectModel/CGI/ItemPage.pm
index c0105f7d6..66fcab755 100644
--- a/testbot/lib/ObjectModel/CGI/ItemPage.pm
+++ b/testbot/lib/ObjectModel/CGI/ItemPage.pm
@@ -1,8 +1,8 @@
 # -*- Mode: Perl; perl-indent-level: 2; indent-tabs-mode: nil -*-
-# Base class for web pages containing a db bound form
+# Base class for web pages containing a DB bound form
 #
 # Copyright 2009 Ge van Geldorp
-# Copyright 2012 Francois Gouget
+# Copyright 2012-2014, 2017-2018, 2022 Francois Gouget
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
diff --git a/testbot/lib/ObjectModel/CGI/Page.pm b/testbot/lib/ObjectModel/CGI/Page.pm
index 1e8f55d31..d5988803c 100644
--- a/testbot/lib/ObjectModel/CGI/Page.pm
+++ b/testbot/lib/ObjectModel/CGI/Page.pm
@@ -2,6 +2,7 @@
 # Base class for web pages
 #
 # Copyright 2009 Ge van Geldorp
+# Copyright 2012, 2014, 2017-2018, 2022 Francois Gouget
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -25,6 +26,29 @@ package ObjectModel::CGI::Page;
 
 ObjectModel::CGI::Page - Base class for web pages
 
+This class provide a generic framework for generating web pages: retrieving
+the HTTP parameters, manipulating cookies, checking the session, handling
+errors, generating the HTTP header, etc.
+
+It also defines their general structure: they shall be composed of a header, a
+body and a footer. That structure can then be further refined by child classes
+to suit their needs.
+
+What it does not do is define what the page should look like: what the banner
+should contain, which CSS files to reference, how to navigate from one page to
+another, etc. It also does not define how to check that the user is allowed to
+access the page or how to display error messages.
+
+All these "look and feel" aspects are delegated to the PageBase object. Thus
+many methods are just trampolines to their PageBase equivalent such that child
+classes can call them and automatically get the appropriate behavior for the
+actual website.
+
+A typical use takes this form:
+
+my $MyPage = MyPage->new($Request, "required-privileges");
+$MyPage->GeneratePage();
+
 =cut
 
 use Exporter 'import';
@@ -35,6 +59,29 @@ use CGI;
 
 my $PageBaseCreator;
 
+
+=pod
+=over 12
+
+=item C<new()>
+
+Creates a new page object.
+
+Parameters:
+=over
+=item Request
+This is the HTTP request leading to this page.
+
+=item RequiredRole
+This is a string specifying which users can access this page.
+
+=back
+
+Both parameters are passed to the PageBase constructor.
+
+=back
+=cut
+
 sub new($$$@)
 {
   my $class = shift;
@@ -55,6 +102,19 @@ sub _initialize($$$)
   #my ($self, $Request, $RequiredRole) = @_;
 }
 
+=pod
+=over 12
+
+=item C<SetPageBaseCreator()>
+
+Sets the function to be used to instantiate a new PageBase object for this
+website. The resulting object can be accessed through GetPageBase().
+
+See also ObjectModel::CGI::PageBase.
+
+=back
+=cut
+
 sub SetPageBaseCreator($)
 {
   ($PageBaseCreator) = @_;
@@ -108,7 +168,7 @@ sub GetParamNames($)
 
 =head1 C<GetParam()>
 
-Returns the specified parameter.
+Returns the specified parameter value.
 Note that unlike CGI::param() this forces the result to scalar context to
 avoid security issues.
 
@@ -153,7 +213,7 @@ sub SetParam($$$)
 
 
 #
-# Session support
+# Session management
 #
 
 sub UnsetCookies($)
@@ -235,7 +295,7 @@ sub GenerateErrorPopup($)
 =head1 C<GetPageTitle()>
 
 This returns the page title as put in the HTML header.
-Note that this may not be valid HTML and thus need escaping.
+Note that this may not be valid HTML and thus may need escaping.
 
 =back
 =cut
@@ -253,7 +313,7 @@ sub GetPageTitle($)
 =head1 C<GetTitle()>
 
 This returns the title for the current web page or email section.
-Note that this may not be valid HTML and thus need escaping.
+Note that this may not be valid HTML and thus my need escaping.
 
 =back
 =cut
diff --git a/testbot/lib/WineTestBot/CGI/PageBase.pm b/testbot/lib/WineTestBot/CGI/PageBase.pm
index b36b28d9a..6d94ae967 100644
--- a/testbot/lib/WineTestBot/CGI/PageBase.pm
+++ b/testbot/lib/WineTestBot/CGI/PageBase.pm
@@ -3,6 +3,7 @@
 #
 # Copyright 2009 Ge van Geldorp
 # Copyright 2010 VMware, Inc.
+# Copyright 2012-2014, 2017-2020, 2022 Francois Gouget
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -24,7 +25,13 @@ package WineTestBot::CGI::PageBase;
 
 =head1 NAME
 
-WineTestBot::CGI::PageBase - Base class for web pages
+WineTestBot::CGI::PageBase - Common boilerplate for the WineTestBot web pages
+
+This class defines the elements common to all the TestBot pages.
+
+This includes services such as how to check the user session and how to
+display errors. And it also defines the general look and feel of the page by
+providing a common banner, navigation menu and cascading style sheets.
 
 =cut
 
@@ -39,6 +46,35 @@ use WineTestBot::CGI::Sessions;
 use WineTestBot::Config;
 use WineTestBot::Utils;
 
+
+=pod
+=over 12
+
+=item C<new()>
+
+Creates a PageBase object for the specified web page.
+
+Parameters:
+=over
+=Page
+This is the page that lead to the creation of this PageBase object.
+
+=item Request
+This is the HTTP request leading to this page.
+
+=item RequiredRole
+This is a role that the user must have in order to be allowed to access this
+page (see UserRoles).
+
+For instance an empty string specifies that any user can access the page,
+even users with no account; while "admin" would specify that only logged-in
+users with the "admin" role can access it.
+
+=back
+
+=back
+=cut
+
 sub new($$$$@)
 {
   my $class = shift;
@@ -77,7 +113,7 @@ sub CreatePageBase($$$@)
 
 
 #
-# Session support
+# Session management
 #
 
 sub UnsetCookies($)
-- 
2.30.2



More information about the wine-devel mailing list