Script of management of a tree
In previous clauses{articles}, we have considered the theory of storage and management of treelike structures of the data and as realized Perl the module for simplification of management of them. Now we shall write a small script upralenija (administrations). The idea of a script is simple - it is required easily and easy, with the help of a script, to operate a catalog tree.
Let's take the standard table in which will be our catalog tree is stored{kept}, in her we shall store{keep} only one tree, realization of a principle of job, at which quantity{amount} of trees neogranicheno, I rassmotrju in following clauses{articles}. So, our table:
CREATE TABLE
my_tree (
id INT (11) NOT NULL AUTO_INCREMENT,
left_key INT (11) NOT NULL DEFAULT 0,
right_key INT (11) NOT NULL DEFAULT 0,
level INT (11) NOT NULL DEFAULT 1,
name VARCHAR (150) NOT NULL,
PRIMARY KEY
id (id),
INDEX
left_key (left_key, right_key, level)
);
Certainly, the quantity{amount} of additional fields (one of them - name) can be neogranicheno.
The concept
For the beginning we shall define{determine}, what functions our script should carry out:
* Creation of the site;
* Editing the site (with an opportunity of change of subordination);
* Removal{Distance} of the site;
* Moving the site on a level upwards;
* Moving the site on a level downwards;
* Moving the site on the order upwards (within the limits of subordination);
* Moving the site on the order downwards (in limits podchiennnosti);
Restriction of access - at all did not take into account, that is authorization of a script, check of access - it is simple otsutsvujut. I shall leave it on your conscience. And in general, easiest, it is simple zaparolirovat` direktiriju a script .htaccess and all...
HTML a pattern *, I all the same have born{have taken out} from a script - I hate to correct HTML in a script, and to you that I do not advise. The pattern will consist of three parts:
* The top part (header.html) - headings and other till the moment of a conclusion of the list of categories (the beginning of the table);
* A line of the list of categories (row.html) - one line of the table of the list of categories;
* The bottom part (footer.html) - the end of the table of a conclusion of the list of categories, the form of creation, editing of a category;
* This structure of patterns has been thought up "on the move", therefore we shall not concentrate attention on its{her} correctness, not it is important.
HTML-code of patterns:
header.html
<html> <head>
<title> the Script of management of a catalog tree </title>
<meta http-equiv = "Content-Type" content = " text/html; charset=windows-1251 ">
<script language = "javascript">
function EditCat (IdCat, NameCat, ParentCat) {
DOCUMENT.GETELEMENTBYID ('TitleForm') .innerHTML = ' TO CHANGE THE CATEGORY ';
document.getElementById ('buttonForm') .value = 'To change';
document. FormCategory.id.value = IdCat;
document. FormCategory.name.value = NameCat;
document. FormCategory.parent.options [ParentCat] .selected = true;
document. FormCategory.doing.value = 'edit';
}
function ClearFormEdit () {
DOCUMENT.GETELEMENTBYID ('TitleForm') .innerHTML = ' TO ADD THE CATEGORY ';
document.getElementById ('buttonForm') .value = 'To add';
document. FormCategory.id.value = 'xx';
document. FormCategory.name.value = ' the New category ';
document. FormCategory.doing.value = 'new';
}
</script>
</head>
<body>
<h1> the Script of management of a catalog tree </h1>
<h2> the List of categories of firms </h2>
<table width = " 100 % " border = "0" cellpadding = "0" cellspacing = "0">
row.html
<tr>
<td> [$prefix $] [$name $] </td>
<td width = "80">
<a href = " * form " onClick = " javascript: EditCat (' [$id $] ', ' [$ name $] ', ' [$ par $] '); ">
To change
</a>
</td>
<td width = "80"> <a href = "? ac = [$ ac $] and doing=delete*id = [$ id $] "> to remove </a> </td>
<td width = "80"> <a href = "? ac = [$ ac $] and doing=level_up*id = [$ id $] "> to the left </a> </td>
<td width = "80"> <a href = "? ac = [$ ac $] and doing=level_down*id = [$ id $] "> to the right </a> </td>
<td width = "80"> <a href = "? ac = [$ ac $] and doing=order_up*id = [$ id $] "> upwards </a> </td>
<td width = "80"> <a href = "? ac = [$ ac $] and doing=order_down*id = [$ id $] "> downwards </a> </td>
</tr>
footer.html
</table>
<a name = "form"> </a>
<table align = "center" width = " 95 % " border = "0" cellpadding = "0" cellspacing = "0">
<form action = "?" method = "post" name = "FormCategory">
<tr> <td colspan = "2"> <h1 id = "TitleForm"> TO ADD THE CATEGORY </h1> </td> </tr>
<tr>
<td> the Name of a category </td>
<td> <input type = "text" value = " the New category " name = "name" size = "60"> </td>
</tr>
<tr>
<td> Submission of a category </td>
<td> <select name = "parent">
<option value = "root"> - Without submission - </option>
[$list_select $]
</select> </td>
</tr>
<tr>
<td colspan = "2"> *nbsp;
<input type = "hidden" name = "id" value = "xx">
<input type = "hidden" name = "doing" value = "new">
<input type = "hidden" name = "ac" value = " [$ ac $] ">
</td>
</tr>
<tr>
<td colspan = "2" align = "center">
<input type = "submit" name = "buttonForm" id = "buttonForm" value = "To add">
*nbsp; *nbsp; *nbsp; *nbsp; *nbsp;
<input type = "reset" value = "To return" onClick = " javascript: ClearFormEdit (); ">
</td>
</tr>
</form>
</table>
</body> </html>
Now I shall explain the separate moments:
* In the first file it is switched on JavaSript as the form of editing and creation one at pressing the link "to change" it is necessary to bring in the corresponding data to the form. By button " Return " of the form, it is required to clear the form of the data of the edited site;
* The text the prisoner in square brackets and a sign on dollar ([$tekst $]) that will be dynamically replaced with our script where:
o [$id $] - the identifier of the site;
o [$name $] - a field name the site, or a hostname;
o [$prefix $] - the space on which is displaced a hostname (depends on a level of the site);
o [$par $] - a serial number of the parental site in select forms of editing (to not confuse with id the parental site!);
o [$ac $] - a casual character set, I shall use current time (against keshirovanija pages);
Code of a script
For the beginning we shall define{determine} where what files at us will lay:
* cgi-bin/admin_tree/
o lib/
+ MP/
* NestedSets.pm
o template/
+ header.html
+ row.html
+ footer.html
o admin.pl
That for file NestedSets.pm, I think, to explain it is not necessary (it is the module described in the previous clauses{articles}), with .html files - too is understandable, there was only one file - admin.pl, we just and shall describe it{him}. So, a code of a script:
*!/usr/bin/perl
* Connection of the basic modules
use strict;
use CGI;
use DBI;
use vars '$query',
'$dbh', * object of connection in a database
'$nested', * object of job with derevoi NestedSets
'%user_vars'; * Global user variables
* We connect the module for job with derevoi NestedSets
use lib ' lib / ';
use Global:: NestedSets;
* We specify variable user variables
$user_vars {'table'} = 'my_tree'; * the Name of the table of a DB
* A connection to base
$dbh = ' DBI '-> connect ('DBI:mysql:database=mybase:host=localhost:port=3306',
'user', 'password') || die $DBI:: errstr;
* We choose the transferred{handed} data
$query = new CGI;
$user_vars {'id'} = $query-> param ('id') || undef; * the Identifier of the site
$user_vars {'doing'} = $query-> param ('doing') || undef; * Made action
* We determine object Global:: NestedSets
$nested = new Global:: NestedSets {DBI => $ dbh, table => $ user_vars {'table'}};
* If any action is made
if ($user_vars {'doing'}) {
* Action - to lift the site on a level upwards
if ($user_vars {'doing'} eq 'level_up') {
$nested-> set_unit_level (unit => $ user_vars {'id'}, move =>'up ');
* Action - to lower{omit} the site on a level downwards
} elsif ($user_vars {'doing'} eq 'level_down') {
$nested-> set_unit_level (unit => $ user_vars {'id'}, move =>'down ');
* Action - to lift the site on the order upwards
} elsif ($user_vars {'doing'} eq 'order_up') {
$nested-> set_unit_order (unit => $ user_vars {'id'}, move =>'up ');
* Action - to lower{omit} the site on the order downwards
} elsif ($user_vars {'doing'} eq 'order_down') {
$nested-> set_unit_order (unit => $ user_vars {'id'}, move =>'down ');
* Action - to remove the site
} elsif ($user_vars {'doing'} eq 'delete') {
$nested-> delete_unit (unit => $ user_vars {'id'});
* Action - to create the site
} elsif ($user_vars {'doing'} eq 'new') {
* We choose the given forms
$user_vars {'name'} = $query-> param ('name') || 'New';
$user_vars {'parent'} = $query-> param ('parent') || 'root';
* We create the site in a tree and it is received it{him} ID
$user_vars {'id'} = $nested-> insert_unit (under => $ user_vars {'parent'});
* We update additional fields of the site
$dbh-> do ('UPDATE.' $ user_vars {'table'}.
' SET name = ". $ user_vars {'name'}. "
WHERE id = '. $ user_vars {'id'}) || die $DBI:: errstr;
* Action - to edit
} elsif ($user_vars {'doing'} eq 'edit') {
* We choose the given forms
$user_vars {'name'} = $query-> param ('name') || 'New';
$user_vars {'parent'} = $query-> param ('parent') || 'root';
* We choose ID the parent of the edited site
my $check = ($nested-> get_parent_id (unit => $ user_vars {'id'}))-> [0];
* If the parental site we make moving varies
if ($check ne $user_vars {'parent'}) {
$nested-> set_unit_under (unit => $user_vars {'id'},
under => $user_vars {'parent'})
}
* We update additional fields of the site
$dbh-> do ('UPDATE.' $ user_vars {'table'}.
' SET name = ". $ user_vars {'name'}. "
WHERE id = '. $ user_vars {'id'}) || die $DBI:: errstr;
}
}
* We give out heading to a browser
print " Content-type: text/html; charset=windows-1251nn ";
* We open a pattern of the top part of page and it is deduced{removed} it{him} on the screen
open (HTML, './template/header.html ') || die ' Can not open file header.html! ';
print <HTML>;
close HTML;
* We open a pattern of a line of the list and it is brought it{him} in a variable
open (HTML, './template/row.html ') || die ' Can not open file row.html! ';
my $line = join (", <HTML>);
close HTML;
* We choose completely all tree and it is sorted on the left key
my $sql = ' SELECT id, name, level
FROM '. $ user_vars {' table '}'.
ORDER BY left_key ';
my $sth = $dbh-> prepare ($sql); $sth-> execute () || die $DBI:: errstr;
* We declare khesh and a variable (counter) with which help we shall define{determine}
* The order of the parental site in the list select forms
my %par = (0 => '0', root => '0'); my $i = 1;
* We declare a variable for formation of the list select forms
my $list_select;
while (my $row = $sth-> fetchrow_hashref ()) {
* We copy a pattern of a line in a time variable
my $temp_line = $line;
* We form a variable for "antikesha"
$$ row {'ac'} = time;
* We form a space before the name of the site
$$ row {'prefix'} = ' *nbsp; *nbsp; *nbsp; *nbsp; ' x ($$ row {'level'} - 1);
* We determine the order of the parental site in the list select forms
$$ row {'par'} = $par {($nested-> get_parent_id (unit => $$ row {'id'}))-> [0]};
$par {$$ row {'id'}} = $i; $i ++;
* We process a line replacing sootvestvujuhhie
$temp_line = ~s / [$ (w +) $] / $$ row {$1}/g;
print $temp_line;
$list_select. = ' <option value = " '. $$ row {'id'}. ' "> '.
$$ row {'prefix'}. $$ row {'name'}. ' </option> ';
}
$sth-> finish ();
* We open a pattern of the bottom part of page and it is written down it{him} in a variable
open (HTML, './template/footer.html ') || die ' Can not open file footer.html! ';
my $footer = join (", <HTML>);
close HTML;
* Vnosiim in a pattern the list select forms
$footer = ~s / [$list_select $] / $ list_select/g;
*... Also we display
print $footer;
* All...
exit;
1;
Actually and all. Apparently, any complexities no, a script in the size less than hundred lines due to use of the module. Certainly, it is necessary to check up still the given forms, maybe, some operations...

|