CGI-Portable
view release on metacpan or search on metacpan
lib/CGI/Portable.pm view on Meta::CPAN
1;
=head2 Content of component module "DemoCamel.pm"
I<This module acts sort of like DemoTextFile.>
package DemoCamel;
use strict;
use warnings;
use CGI::Portable;
sub main {
my ($class, $globals) = @_;
my $users_choice = $globals->current_user_path_element();
my $filename = $globals->pref( $users_choice );
my $filepath = $globals->physical_filename( $filename );
SWITCH: {
$globals->add_no_error();
open( FH, $filepath ) or do {
$globals->add_virtual_filename_error( 'open', $filename );
last SWITCH;
};
local $/ = undef;
defined( my $file_content = <FH> ) or do {
$globals->add_virtual_filename_error( "read from", $filename );
last SWITCH;
};
close( FH ) or do {
$globals->add_virtual_filename_error( "close", $filename );
last SWITCH;
};
$globals->set_page_body( $file_content );
}
if( $globals->get_error() ) {
$globals->append_page_body(
"Can't show requested screen: ".$globals->get_error() );
$globals->add_no_error();
}
}
1;
=head2 Content of component module "DemoPanda.pm"
I<This module acts sort of like nothing I've ever seen.>
package DemoPanda;
use strict;
use warnings;
use CGI::Portable;
sub main {
my ($class, $globals) = @_;
$globals->set_page_body( <<__endquote );
<p>Food: @{[$globals->pref( 'food' )]}
<br />Color: @{[$globals->pref( 'color' )]}
<br />Size: @{[$globals->pref( 'size' )]}</p>
<p>Now let's look at some files; take your pick:
__endquote
$globals->navigate_url_path( $globals->pref( 'file_reader' ) );
foreach my $frag (@{$globals->pref( 'files' )}) {
my $url = $globals->url_as_string( $frag );
$globals->append_page_body( "<br /><a href=\"$url\">$frag</a>" );
}
$globals->append_page_body( "</p>" );
}
1;
=head1 DESCRIPTION
The CGI::Portable class is a framework intended to support complex web
applications that are easily portable across servers because common
environment-specific details are abstracted away, including the file system type,
the web server type, and your project's location in the file system or uri
hierarchy.
Also abstracted away are details related to how users of your applications
arrange instance config/preferences data across single or multiple files, so they
get more flexability in how to use your application without you writing the code
to support it. So your apps are easier to make data-controlled.
Application cores would use CGI::Portable as an interface to the server they are
running under, where they receive user input through it and they return a
response (HTML page or other data type) to the user through it. Since
CGI::Portable should be able to express all of their user input or output needs,
your application cores should run well under CGI or mod_perl or IIS or a
Perl-based server or a command line without having code that supports each type's
individual needs.
That said, CGI::Portable doesn't contain any user input/output code of its own,
but allows you to use whatever platform-specific code or modules you wish between
it and the actual server. By using my module as an abstraction layer, your own
program core doesn't need to know which platform-specific code it is talking to.
As a logical extension to the interfacing functionality, CGI::Portable makes it
easier for you to divide your application into autonomous components, each of
which acts like it is its own application core with user input and instance
config data provided to it and a recepticle for its user output provided. This
module would be an interface between the components.
This class has 5 main types of functionality, or sets of properties that exist
in parallel but are fully/mostly independant from each other. As such, it
could conceptually be split into 5 physical modules, some of which could be
used on their own, but they are actually contained in this one module for
simplicity of use (just one object for user code to keep track of). The 5
functionality sets could be called: Errors, Files, Request, Response, Misc.
=head2 Errors - Manages error list for operations
This class implements methods that manage an "error list" property,
which is designed to accumulate any error strings that should be printed to the
program's error log or shown to the user before the program exits. What
constitutes an error condition is up to you, but the suggested use is for things
that are not the web user's fault, such as problems compiling or calling program
modules, or problems using file system files for settings or data. The errors
list is not intended to log invalid user input, which would be common activity.
Since some errors are non-fatal and other parts of your program would still
work, it is possible for several errors to happen in parallel; hence a list.
At program start-up this list starts out empty.
An extension to this feature is the concept of "no error" messages (undefined
strings) which if used indicate that the last operation *did* work. This gives
lib/CGI/Portable.pm view on Meta::CPAN
DESCRIPTION for more details.
=head2 get_file_path_ref()
This method returns a reference to the file path object which you can then
manipulate directly with File::VirtualPath methods.
=head2 file_path_root([ VALUE ])
This method is an accessor for the "physical root" string property of the file
path, which it returns. If VALUE is defined then this property is set to it.
This property says where your project directory is actually located in the
current physical file system, and is used in translations from the virtual to
the physical space. The only part of your program that should set this method
is your thin startup shell; the rest should be oblivious to it.
=head2 file_path_delimiter([ VALUE ])
This method is an accessor for the "physical delimiter" string property of the
file path, which it returns. If VALUE is defined then this property is set to
it. This property says what character is used to delimit directory path levels
in your current physical file system, and is used in translations from the
virtual to the physical space. The only part of your program that should set
this method is your thin startup shell; the rest should be oblivious to it.
=head2 file_path([ VALUE ])
This method is an accessor to the "virtual path" array property of the file path,
which it returns. If VALUE is defined then this property is set to it; it can
be an array of path levels or a string representation in the virtual space.
This method returns an array ref having the current virtual file path.
=head2 file_path_string([ TRAILER ])
This method returns a string representation of the file path in the virtual
space. If the optional argument TRAILER is true, then a virtual file path
delimiter, "/" by default, is appended to the end of the returned value.
=head2 navigate_file_path( CHANGE_VECTOR )
This method updates the "virtual path" property of the file path by taking the
current one and applying CHANGE_VECTOR to it using the FVP's chdir() method.
This method returns an array ref having the changed virtual file path.
=head2 virtual_filename( CHANGE_VECTOR[, WANT_TRAILER] )
This method uses CHANGE_VECTOR to derive a new path in the virtual file-system
relative to the current one and returns it as a string. If WANT_TRAILER is true
then the string has a path delimiter appended; otherwise, there is none.
=head2 physical_filename( CHANGE_VECTOR[, WANT_TRAILER] )
This method uses CHANGE_VECTOR to derive a new path in the real file-system
relative to the current one and returns it as a string. If WANT_TRAILER is true
then the string has a path delimiter appended; otherwise, there is none.
=head2 add_virtual_filename_error( UNIQUE_PART, FILENAME[, REASON] )
This message constructs a new error message using its arguments and appends it to
the error list. You can call this after doing a file operation that failed where
UNIQUE_PART is a sentence fragment like "open" or "read from" and FILENAME is the
relative portion of the file name. The new message looks like
"can't [UNIQUE_PART] file '[FILEPATH]': $!" where FILEPATH is defined as the
return value of "virtual_filename( FILENAME )". If the optional argument REASON
is defined then its value is used in place of $!, so you can use this method for
errors relating to a file where $! wouldn't have an appropriate value.
=head2 add_physical_filename_error( UNIQUE_PART, FILENAME[, REASON] )
This message constructs a new error message using its arguments and appends it to
the error list. You can call this after doing a file operation that failed where
UNIQUE_PART is a sentence fragment like "open" or "read from" and FILENAME is the
relative portion of the file name. The new message looks like
"can't [UNIQUE_PART] file '[FILEPATH]': $!" where FILEPATH is defined as the
return value of "physical_filename( FILENAME )". If the optional argument REASON
is defined then its value is used in place of $!, so you can use this method for
errors relating to a file where $! wouldn't have an appropriate value.
=cut
######################################################################
sub get_file_path_ref {
return( $_[0]->{$KEY_FILE_PATH} ); # returns ref for further use
}
sub file_path_root {
my ($self, $new_value) = @_;
return( $self->{$KEY_FILE_PATH}->physical_root( $new_value ) );
}
sub file_path_delimiter {
my ($self, $new_value) = @_;
return( $self->{$KEY_FILE_PATH}->physical_delimiter( $new_value ) );
}
sub file_path {
my ($self, $new_value) = @_;
return( $self->{$KEY_FILE_PATH}->path( $new_value ) );
}
sub file_path_string {
my ($self, $trailer) = @_;
return( $self->{$KEY_FILE_PATH}->path_string( $trailer ) );
}
sub navigate_file_path {
my ($self, $chg_vec) = @_;
return( $self->{$KEY_FILE_PATH}->chdir( $chg_vec ) );
}
sub virtual_filename {
my ($self, $chg_vec, $trailer) = @_;
return( $self->{$KEY_FILE_PATH}->child_path_string( $chg_vec, $trailer ) );
}
sub physical_filename {
my ($self, $chg_vec, $trailer) = @_;
return( $self->{$KEY_FILE_PATH}->physical_child_path_string(
$chg_vec, $trailer ) );
}
sub add_virtual_filename_error {
my ($self, $unique_part, $filename, $reason) = @_;
my $filepath = $self->virtual_filename( $filename );
defined( $reason ) or $reason = $!;
$self->add_error( "can't $unique_part file '$filepath': $reason" );
}
sub add_physical_filename_error {
my ($self, $unique_part, $filename, $reason) = @_;
my $filepath = $self->physical_filename( $filename );
( run in 1.739 second using v1.01-cache-2.11-cpan-364913b4093 )