[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