Module as_admintool written primarily for people (like me) who often
execute administering tasks through a WEB-interface:
run SQL queries, backup/restore data from/to SQL server, and so on.
First,I wanted to have a flexible solution, that allows to add functionality as easy as possible.
Second, I desided to make all requests in AJAX manner (no need to redraw a whole page, asynchronous calls etc.)
As a result, as_admintool was implemented as an empty container, and all 'real' jobs reside
in plugin modules. A few ready-to-use plugins included in distributive.
Anyone can develop and 'attach' his own plugin module, that can be far from 'administering' tasks
- it's a matter of Your needs and fantasy.
All plugin modules in distributive use AJAX calls, so the main screen is drawn only once, then built-in javascript functions sends data through a POST request to the server by XMLHttpRequest, receive result, and make some dynamic changes depending on it (for example, draw returned HTML code containing execution result).
Attention: Javascript and DHTML widely used, so browser compatibility
should be tested before publishing production version of Your application.
Make a decision what plugin modules You'll need in Your administering tasks, and include them by require_once() or include_once() functions after the line require_once('as_admintool.php') Listing 1: header part
require_once('as_admintool.php');
require_once('as_admintool_sqlqry.php'); // SQL queries plugin
Now You can create a CAsAdminTool object and fill it with some pages.
You can add more than one page of any registered type, for example, make two independent pages for running SQL queries.
(As we'll see later, each query page can have it's own predefined queries list).
When all pages added, just call Draw() method.
Listing 2: create CAsAdminTool object, add pages and draw it.
$adminobj = new CAsAdminTool(800,620); // desired width and height passed $adminobj->AddPage(ADM_SQLQUERY,'SQL Queries page 1', 'predef-qry1.txt'); $adminobj->AddPage(ADM_SQLQUERY,'SQL Queries (page 2)', 'predef-qry2.txt'); $adminobj->Draw();
Now, we have a good looking HTML page with all our tools. But who will do the job when our user
press 'Execute' button' ?
as_admintool designed in self-contained manner, so all plugin modules must send queries to the
same URL that draws admin screen. (We'll have a closer look at plugin design later).
To provide 'receiving' client request and executing a job, You should add 'executing' code somewhere
BEFORE any HTML drawing (including html 'Header' sends ! like cookies etc).
Otherwise this HTML code will be AJAX-sent to the client before query result, what is wrong.
From the other hand, 'request handling' code must be inserted into Your page after all security checks,
to prevent unauthorized calls. So You have to put CAsAdminTool::PerformAction()
call in the right place.
Next listing is a full code example (we assume there is a special session variable containing user access level):
Listing 3: full code example
require_once('as_admintool.php');
require_once('as_admintool_sqlqry.php'); // as_admintool: executing SQL queries plugin
// localize interface here or just change titles, if needed:
$as_iface['parameters'] ='Query parameters';
$as_iface['predef-qry'] ='predefined queries list...';
$as_iface['execqry'] ='Execute Qry';
$as_iface['explainqry'] ='Show execution plan';
$as_iface['qryresult'] ='Query result';
$as_iface['msg_waiting'] ='Waiting for server reply...';
// some CSS tuning
$as_cssclass['pagebody'] = 'frmtable';
if(!isset($_SESSION)) session_start();
$access = $_SESSION['access_level']; // Have You admin rights ?
ConnectDb(); // some function for connecting to your DB
$as_adm_qryaccess = 2; // sqlqry plugin can work in three access levels : 0-1-2
# Client request executing code: this is a mandatory line,
# You add it before any HTML drawing code !
# You can check user access level before this, to avoid unauthorized calls
if(!empty($admt_call_handler)) CAsAdminTool::PerformAction();
HTML_Header(); // function that draws your html header block, at least <HTML><BODY>
and all CSS styles or css file reference...
if($access gt; 1 ) {
$adminobj = new CAsAdminTool;
$adminobj-gt;SetJsPath('../scripts/'); // if as_jsfunclib.js file is not in cur.dir
$adminobj-gt;AddPage(ADM_SQLQUERY,'SQL Queries', 'predef-qry1.txt');
$adminobj-gt;AddPage(ADM_SQLQUERY,'SQL Queries (page 2)', 'predef-qry2.txt');
$adminobj-gt;Draw();
}
else echo "access denied !";
if(!empty($admt_call_handler)) CAsAdminTool::PerformAction();
Here is a full method definition in CAsAdminTool.
| constructor: CAsAdminTool($width='920',$height='600') |
$width - width of the property sheet containing all admin pages; 920 by default $height - height, 600 by default. Sample: $obj = new CAsAdminTool(800,400); |
| AddPage($pagetype, $pagetitle, $userparam1='', $userparam2='',$userparam3='') | Register new page that will be drawn.
$pagetype - string ID of one of registered types $pagetitle - string will be a title in the tab for this page. $userparam1,2,3 - optional parameters that will be passed to the drawing page function, so every page of this type can have some differences. In a sample.php we use it to have different predefined query lists on "SQL query" pages, and to work with different davabases on server. Sample: $obj->AddPage('sqlqry', 'Sql query - page 1','','mydatabase'); |
| SetJsPath($strk) | Sets path to the module as_jsfunclib.js, used by javascript functions inside plugins
Sample: $obj->SetJsPath('../scripts/'); |
| Draw($initpage=false) | This is a final method that draws the whole HTML code for Your
administrator pages. Parameter $initpage can set initially active page number.
Sample: $obj->Draw(2); |
| PerformAction() | Special 'static' function that handles all requests from client. It analizes POST or GET passed parameter adm_action_type,
and depending on it's value calls respective plugin's handler function. As mentioned above, You have to place
this function call in the right place (before any HTML output, but after security checks).
Sample: CAsAdminTool::PerformAction(); |
To add SQL query page to Your admin screen, You must add a line in your code (after including 'as_admin_tool.php'):
require_once('as_admintool_sqlqry.php');
This inclusion registers a new page type 'sqlqry', so now You can add as many SQL pages as You want
by calling AddPage() :
$adminobj-gt;AddPage('sqlqry','Sql Queries, Page NN');
Using "as_admintool_sqlqry" details
AddPage() for sqlqry type has a following 'user parameters':
User Parameter 1 is a var to pass pre-defined SQL queries, and second - for database name
(if it's not a default database already connected earlier by Your code).
Predefined Queries
sqlqry page can have a pre-defined queries, that user won't have to write manually, he just select query name in select-box,
and SQL text is automatically placed into the text field.
You can prepare an array variable containing predefined queries, in the next form :
each row of this array is an array('query label', 'SQL query text' [,parameter_1_prompt [,...])
If you have that variable, use it as a parameter when calling AddPage:
$myqueries = array();
$myqueries[] = array('Find dept',"SELECT * from depts where deptname like '&P1%'",'search for dept:');
$myqueries[] = array('Find person',"SELECT * from employees where name like '&P1%'",'person name');
$adminobj->AddPage('sqlqry', 'My queries',$myqueries);
The second way: You can save predefined queries list is in a text file.
One line in this file must contain all the same items for the query, delimited by '|': (label | SQL text [|parameter prompts...])
Employees list in the dept|SELECT * from employees WHERE deptname LIKE '&P1%'|Department name
Get all goods for class and name|SELECT * from goods WHERE good_class='&P1' AND good_name='&P2'|class|good name
Example: Two-queries in one call|SELECT SYSDATE(){CRLF}/{CRLF}SELECT * FROM mytable
As You can see, first field is a 'title' for a query, second is a query itself, and the rest are the prompts for all parameters,
if query contains them and you need to have user-friendly interface.
Constants in as_admintool_sqlqry
ASADM_SQLQUERY holds a unique id for plugin's type, so it's better write everywhere AddPage(ASADM_SQLQUERY,...).
ASADM_MAXRECORDS is a maximum number or records, that can be returned from SQL query executing.
Default is 200. Even if query does not contain LIMIT N1,N2 option, output will be stopped after reaching ASADM_MAXRECORDS's item.
To turn limiting Off, just set it to 0.
$as_adm_qryaccess - this variable relates to current user access level.
Yo can set it to the one of three values, before calling CAsAdminTool::Draw() method:
ASADM_QRYPARAM is a number of "parameter" fields on SQL Query form. Default is 4. You can adjust this value. In a form all parameters are drawn by four items per row.
User defined "HREF" columns
What if You d'like to have some "A HREF" anchor tags in a query result, that open desired page, related to current record ?
For that case a special feature was added: user defined columns.
All You need is to add one or more strings in Your query definition, after all parameters titles (or in mixed manner).
User column definition Syntax :
#HREF ^ {column_number} ^ HTML-code_with_{ID}
As You see, every column definition must begin with "#HREF" string (user column flag), followed by field number and HTML code,
delimited with "^" char.Example
We have a query, returning employee list, with employee ID in first column: SELECT emp_id, emp_name ... FROM employees ...
And we want to have a column with <A HREF> tag, that opens full info page about employee, say "fullinfo.php?emp_id=NNN".
For this case we construct a query definition:
Query title|SELECT emp_id, emp_name ... FROM employees|#HREF^0^<A HREF='fullinfo.php?emp_id={ID}'>open info</a>
Note that as column numbers are zero-based, our (first) column has a number 0.
$myqueries[] = array('Find person',"SELECT * from employees where name like '&P1%'",'person name',"#HREF^0^....");
require_once('as_admintool_backup.php'); // register plugin after as_admintool included line
...
$bckp_folder = 'mybackups/'; // I will save all backups in this folder.
$bckp_list = array('mytable1','mytable2');
$db_name = 'mydatabase';
$adminobj->AddPage(ASADM_BACKUP,'my backups', $bckp_list, $bckp_folder, $db_name);
...
$adminobj->Draw(); // draw admin screen
Like in other plugins, the second parameter is a label for the tab.
The third parameter ($bckp_list) can be either an array variable with all table names You want to backup in one file, or just a text file name (that file must contain table names, one per line). If You want to backup ALL tables in database, just pass an empty string in this parameter.
The optional fourth parameter is a folder where You want to save a backup file. If omitted, default folder is used. Default folder is set in variable $as_admt_bckpfolder, so You can change it.
The optional 5-th parameter is a database name, needed if You want to select another database.
// pass an array with all table names:
$mytables = array('users','employees','depts','orderlist','clientlist');
$adminobj->AddPage(ASADM_BACKUP,'my backups', $mytables, $bckp_folder,'mydb'); // add a page with a backup FORM
Global variables and constants in as_admintool_backup:
ASADM_BACKUP_GZIP - defines saving mode for backup files, if non zero, backup file will be
saved in gzip format, extension '.gz' is added to the filename. Default : 1.
$as_admt_bckpfolder - default folder for backup files. Default: 'backup/'
$as_admt_bcktemplate is a template for created backup file name. It can contain 'date elements' strings,
that will be replaced with current date:
| YYYY | year (4 digits) |
| YY | year (2 digits) |
| MM | month (2 digits with leading zero) |
| DD | day (2 digits) |
| HH | Hours |
| MI | Minutes |
| SS | Seconds |
Default template value is 'backup-YYYY-MM-DD-HHMI'.
File extension '.xml' is added by program, so don't include it into template.
If user has entered his own file name before starting backup, that name will override default template.
To add 'Restore' page to Your "admin screen", You must add a line in your code (after including 'as_admin_tool.php') and add a page with a type 'restore':
require_once('as_admintool_restore.php');
...
$adminobj->AddPage('restore','Restore from backups',$backupfolder,$db_name);
...
$adminobj->Draw();
Using "as_admintool_restore" plugin
Like a previous plugin, as_admintool_backup, this module has a variable 'default' backup folder, it's the same var:
$as_admt_bckpfolder
You can have multiple 'restore' pages on Your "admin screen", and each of them can work with different backup folder
and different database.
You have to pass this folder (and database name) in the 3-rd (and 4-rd) parameter of AddPage() method
($backupfolder in example above).
Any file in 'backup' folder, with extension '.xml' or '.gz' will be treated as 'backup-file'
and placed into 'backup files' select box.
You can 'protect' some file names from deleting or overwriting by filling a special array var: $asdt_fmgr_protect.
Using "as_admintool_filemgr" plugin
Just add a line with require_once for this module, and Addpage() somewhere in Your code.
Prepare an array with all folders that You want to manage and pass it in the AddPage() function.
Every array item can be scalar var (in that case it's value will be a folder exact name. and a title shown in select box),
on two-dimensional array: the first element must be a existing folder name with ending slash ("scripts/"),
and second one - it's label shown in select box:
$folders = array( array('scripts/', 'My scripts folder'),
array('config/', 'Config files'),
'img/');
$adminoj-gt;AddPage(ASADM_FILEMGR,'Ôàéë-ìåíåäæåð', $folders);
...
There are two constants in plugin:
Some javascript functionality has moved to a separate module, as_jsfunclib.js, to make it reusable in many scripts.
This modile is not absolutely my invention, some functions were found in internet, adapted and gathered into one file.
For example, to create XMLHttpRequest object, well known function NewXMLHttpRequest() is used.
To make a parameter string containing all fields in HTML form, I use ComputeParamString(frmname, skipempty, fldlist),
where frmname is passed form name, skipempty is a parameter that orders to skip empty values,
and fldlist is optional array holding form field names - if You pass this array, only these fields will be collected,
the rest are skipped. Investigate included plugin modules and You'll find how these functions used.
When adding "import data" page to Your admin tool screen, You have to pass "base" folder, that contains text data files - only this folder will be searched for source text files. Supported source file extensions are "txt", "csv" and "tdf" - the rest of a folder contents is ignored. (Of course, this extensions list can be changed in the source code).
Using sqlimport plugin Example
require_once('as_admintool.php');
require_once('as_admintool_slqimport.php');
$tables = array('employees','departments','salaries'); # only these tables can be imported from txt files
$adminobj = new CAsAdminTool(800,620);
$adminobj->AddPage(ASADM_SQLIMPORT,'Data importing', 'data-files/',$tables);
$adminobj->Draw();
AddPage parameters fro sqlimport plugin
As You could see in example, AddPage can pass two parameters: first is as tring containing folder (path) to
the source text files. This parameter is optional, if ofitted, files will be searched in current folder.
How it works
On the "import" page You have to choose on of available tables in select box N1, and one of source files
in select box N2 (this list can be instantly refreshed by pressing "refresh files" button, without reloading
the whole page).
When choice done, press "Select fields for columns..." button. On this action, selected text file is parsed on server,
delimiter chat is autodetected (by maximal "splitting result" of it's lines). Then the HTML code for choosing a field for
each text filke "data column" is computed and sent to the client.
This code is a grid, that shows first 20 parsed lines from text file, and select boxes for each data column, where
You will choose data table field for every of them (if no field selected, this column of data will be ignored)
Importing can be done with or without cleaning (truncating) of a target table. (Use a respective checkbox for this option )