Embedding Perl in HTML with Mason Chapter 8: Building a Mason Site-P2

Chia sẻ: Thanh Cong | Ngày: | Loại File: PDF | Số trang:29

lượt xem

Embedding Perl in HTML with Mason Chapter 8: Building a Mason Site-P2

Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Tham khảo tài liệu 'embedding perl in html with mason chapter 8: building a mason site-p2', công nghệ thông tin, kỹ thuật lập trình phục vụ nhu cầu học tập, nghiên cứu và làm việc hiệu quả

Chủ đề:

Nội dung Text: Embedding Perl in HTML with Mason Chapter 8: Building a Mason Site-P2

  1. Chapter 8: Building a Mason Site-P2 • left_side_menu.mas This component is longer than any of the previous ones, but not significantly more complicated. Several features are worth noting here. The first is that the menu changes based on whether or not the return value from $User->is_logged_in() is true. The $User object was generated in the /syshandler component and may represent either a guest user or a real logged-in user. If a user has logged in, she sees options that allow her to create a new project, edit any projects for which she may have editing access, change her user account information, and log out. The link to edit projects appears only if she actually has editing access to one or more projects. Note that we construct all URLs using the /lib/url.mas component, which we will examine later. This component handles the construction of properly escaped URLs of arbitrary complexity. Using this component for all URLs would make it easy to add in something like URL-based sessions later on. For the Logout URL, we are regenerating the URL, and query string, if any, for the current page. We do this because the component that handles logouts, /users/logout.html, will redirect the client back to the page where she clicked on the Logout link. Getting back to the menu component, we can see that if the user is not logged in, we generate a form that POSTs to the /user/login_submit.html component. Again, we will be passing in the current URL and query string
  2. parameters to the login component so that it can send the user back where she came from, with either a cookie indicating a successful login or an error message. That error message is handled just above where the form starts, where we check the variable $login_error. We take advantage of the fact that a POST request can also have a query string in order to put the %caller_args hash into the query string, where we can be sure that keys and values will be received by the server in the right order. If we put the keys and values in the form itself as hidden fields, there is no guarantee that the browser will submit them in the order we specify. A bit further on, we see that if the $User->is_admin() method returns true we add a few extra links for the site administrators. The section for this component shows a common application of filtering. We first determine the URL for our current page. Then, if there is a link in the menu that matches that page, we replace the anchor tag ( ) with a bold tag ( ). We need to special-case the URL /index.html because the link for this particular page is simply . We do this with a regular expression so that it'll work properly if we decide to add links to other directories here in the future.
  3. The site Welcome, username %> Home   Search
  4. All the projects Browse by category % if ( $User->is_logged_in ) {   Add a new project
  5. % if ( $User->has_projects ) { Edit one of your projects % } % }   % if ( $User->is_logged_in ) {
  6. &>">Logout Edit your account % } elsif ( $r->uri !~ m,/login_form, ) { Login % if ($login_error) { % }
  7. query => { caller_url => $r- >uri, caller_args => \%query_args } &>" method="POST"> Username: Password:
  8. path => '/users/forgot_password.html' &>">Forgot my password New user % } % if ($User->is_admin) {   Admin Edit users
  9. Edit categories % }   Complaints / Compliments?  
  10. $username => '' $login_error => '' my %query_args = $m->request_args; # These arguments are intended for use on this page and do not need # to be passed through to the login_submit.html component delete @query_args{ 'username', 'login_error' }; (my $url = $r->uri) =~ s/index\.html$//; $url = $m->scomp( '/lib/url.mas', path => $url ); s{([^
  11. • /lib/url.mas The purpose of this component is to construct a properly escaped and formatted query string based on the parameters it receives. It would not be able to handle nested data structures or objects as values of the %query hash. For these, it would be necessary for us to use a session mechanism rather than trying to pass them around in the URL.3 Because the URI object's query_form() method doesn't allow hash references, we convert any hash references we find in the %query values to array references before passing %query to the query_form() method. While right now we are not taking advantage of most of the parameters this component allows us to pass, these were easy to implement and may come in handy in the future. The backslash at the end of the last line is there to ensure that we don't accidentally add a new line to the URL. $scheme => 'http' $username => undef $password => '' $host => undef $port => undef $path %query => ( )
  12. $fragment => undef my $uri = URI->new; if ($host) { $uri->scheme($scheme); if (defined $username) { $uri->authority( "$username:$password" ); } $uri->host($host); $uri->port($port) if $port; } # Sometimes we may want to path in a query string # but the URI module will escape the question mark. my $q;
  13. if ( $path =~ s/\?(.*)$// ) { $q = $1; } $uri->path($path); # If there was a query string, we integrate it into the query # parameter. if ($q) { %query = ( %query, split /[&=]/, $q ); } # $uri->query_form doesn't handle hash ref values properly while ( my ( $key, $value ) = each %query ) { $query{$key} = ref $value eq 'HASH' ? [ %$value ] : $value; } $uri->query_form(%query) if %query;
  14. $uri->fragment($fragment) if $fragment; canonical | n %>\ • /latest_projects.mas With this component, we display the five most recently added projects. These projects are then displayed with their names and their creation dates. The date, which is returned from MySQL in the format of 'YYYY-MM-DD' , is formatted via the /lib/format_date.mas component. This is the first time we have seen a project link. All project links are of the form /project/.html. Obviously, we do not actually have files with names like /project/10012491.html. These URLs are intercepted by a dhandler instead. Underneath these links we show the total count of projects in the system. Since we want this site to work properly from the moment it is made live, we also have to handle the case in which we have no projects in the system. Hopefully, this code path will not be followed for very long, but it is important. Latest projects
  15. % if ($count) { % while (my $project = $projects->next) { name | h %> $project- >creation_date, short => 1 &> % }  
  16. project 1 ? 's' : '' %> in the system. % } else { No projects in the system. % } my $count = $Schema->Project_t->row_count; # This grabs a list of the five most recent projects, sorted first # by descending creation date, and then by name in ascending. my $projects = $Schema->Project_t->all_rows ( order_by => [ $Schema->Project_t- >creation_date_c, 'desc', $Schema->Project_t->name_c, 'asc' ],
  17. limit => 5, ); • /lib/format_date.mas This simple component takes a date as returned by MySQL and turns it into a friendlier format. It can produce either a short ("Feb 4, 1970") or long ("February 04, 1970") date. The particular formats used were chosen because they are understandable to (English-reading) users around the world. A purely numeric format such as "02/10/2002" can be ambiguous, depending on whether you are expecting the American or European ordering of the date components. A smarter site might allow users to specify their preference as part of their account. $date $short => 0 my $format; if ( $short ) { $format = '%b %d, %Y'; } else {
  18. $format = '%B %e, %Y'; } # remove time if it exists $date =~ s/ .*$//; strptime( $date, '%Y-%m-%d' )- >strftime($format)%>\ • /index.html Hey, there's nothing there! Our index page simply calls a number of other components and provides almost nothing of its own. It does override the title method defined in the /autohandler component. The method call will call the title method in the /autohandler component which, as we saw previously, simply produced the string "Perl Apprenticeship Site". After this we add " - Home" to identify the page. So now we should examine the components that actually make up our index page.
  19. - Home • /welcome.mas This component contains exactly one piece of code. In the course of our paragraph encouraging participation in the site, we want to offer context- appropriate links. Guest users should be encouraged to log in if they have an account or to create a new account. But a user who has already logged in should see links to create a new project. This was something we did just because we could. It makes the site a little smarter and was easy to do with Mason. Welcome to the Perl Apprenticeship Site Way back at OSCON 2001, Adam Turoff (a.k.a. Ziggy) suggested that
  20. Perl needed a way to hook up people with lots of skill and experience, but little time, with people who had a desire to learn and free time, but not as much experience. In other words, we needed a Perl apprenticeship site. Meanwhile, Ken Williams and I had just started working on the Mason book and we knew we wanted to have an example site as one of our chapters. We also knew we didn't want something like a web store. Boring! And useless too, since neither of us needed a web store. So when Ziggy announced his idea, Ken suggested that we implement it for the book. It helps us because it gives us something to fill Chapter 8,
Đồng bộ tài khoản